在C中通过引用传递数组
我是C的新手,我有一个疑问 由于C函数创建其参数的本地副本,我想知道为什么下面的代码会按预期工作:在C中通过引用传递数组,c,arrays,function,reference,C,Arrays,Function,Reference,我是C的新手,我有一个疑问 由于C函数创建其参数的本地副本,我想知道为什么下面的代码会按预期工作: void函数(int数组[]){ 数组[0]=4; 数组[1]=5; 数组[2]=6; } int main(){ int数组[]={1,2,3}; 函数(数组); printf(“%d%d%d”,数组[0],数组[1],数组[2]); 返回0; } 线路输出为4 5 6 为什么这样做有效,而下面的不行 void函数(整数){ 整数=2; } int main(){ 整数=1; 函数(整数);
void函数(int数组[]){
数组[0]=4;
数组[1]=5;
数组[2]=6;
}
int main(){
int数组[]={1,2,3};
函数(数组);
printf(“%d%d%d”,数组[0],数组[1],数组[2]);
返回0;
}
线路输出为4 5 6
为什么这样做有效,而下面的不行
void函数(整数){
整数=2;
}
int main(){
整数=1;
函数(整数);
printf(“%d”,整数);
返回0;
}
在这种情况下,输出仅为1
简短版本:如果父变量作为数组传递,为什么函数可以修改它们的值
谢谢大家! 在“按引用传递”和“按值传递”之间存在差异
Pass-by-reference指向内存中的一个位置,其中Pass-by-value直接传递值,数组变量始终是reference,因此它指向内存中的一个位置。默认情况下,整数将按值传递数组名称是指向数组中第一个元素的指针。在第一个代码示例中,您传递了一个指向包含第一个数组元素的内存位置的指针。在第二个代码示例中,您通过值传递了一个整数,因此它与名为“integer”的局部变量无关 检查那个链接 按参考传递和按值传递
传递给函数的数组将转换为指针。当您将指针作为参数传递给函数时,只需给出内存中变量的地址即可。因此,当您修改数组单元格的值时,您可以编辑给定给函数的地址下的值 将简单整数传递给函数时,将在堆栈中复制该整数;在函数中修改该整数时,将修改该整数的副本,而不是原始副本 C语言中不同类型内存的提醒 在C中,我们可以使用三种类型的内存:
- 用于局部变量和函数调用的堆栈:当我们在main()中创建变量时,我们使用堆栈存储变量,当调用函数时,给方法的参数在堆栈中注册。当我们退出一个函数时,我们“弹出”这些参数以返回到原始状态,在调用函数之前使用变量。(轶事:stackoverflow是指我们对堆栈进行黑客攻击,在函数中使用先前的变量,而不将其作为参数传递)
- 与动态分配的内存相对应的堆:当我们需要大量数据时,我们使用此堆,因为堆栈被限制为几兆字节
- 存储程序指令的代码
void function(int *integer)
{
*integer = 2;
}
int main()
{
int integer = 1;
function(&integer);
printf("%d", integer);
return 0;
}
这是由于数组趋向于衰减为指针这一事实造成的
int a[] = { 1, 2, 3 };
int* p = a; // valid: p is now the address of a[0]
a = p; // NOT valid.
printf("a = %p\n", a);
printf("p = %p\n", p); // prints same address as a
a
和p
将打印相同的值
与其他人所说的相反,a
不是指针,它可以简单地衰减为指针
在第一个function()
中,传递的是数组第一个元素的地址,函数体会取消对该元素的引用。事实上,编译器将函数原型视为:
void function(int* array /*you wrote int array[]*/){
array[0] = 4;
array[1] = 5;
array[2] = 6;
}
function(&array[0]);
这必须发生,因为您说的是“大小未知的数组”(int-array[])。编译器无法保证推断按值传递所需的堆栈数量,因此它会衰减为指针
----编辑----
让我们结合两个例子,使用更独特的名称使事情更清楚
#include <stdio.h>
void func1(int dynArray[]) {
printf("func1: dynArray = %p, &dynArray[0] = %p, dynArray[0] = %d\n",
dynArray, &dynArray[0], dynArray[0]);
}
void func2(int* intPtr) {
printf("func2: intPtr = %p, &intPtr[0] = %p, intPtr[0] = %d\n",
intPtr, &intPtr[0], intPtr[0]);
}
void func3(int intVal) {
printf("func3: intVal = %d, &intValue = %p\n",
intVal, &intVal);
}
int main() {
int mainArray[3] = { 1, 2, 3 };
int mainInt = 10;
printf("mainArray = %p, &mainArray[0] = %p, mainArray[0] = %d\n",
mainArray, &mainArray, mainArray[0]);
func1(mainArray);
func2(mainArray);
printf("mainInt = %d, &mainInt = %p\n",
mainInt, &mainInt);
func3(mainInt);
return 0;
}
在func1
和func2
中,“dynArray”和“intPtr”是局部变量,但它们是指针变量,从main接收“mainArray”的地址
此行为特定于阵列。如果要将数组放入结构中,则可以通过值传递它。在第一个代码中,传递指向数组顶部元素的数组地址。因此,当您修改函数中的值并返回到主函数时,您仍然在访问同一地址中的同一数组。这称为按引用传递
但是,在第二种情况下,整数的值从主函数复制到被调用函数。换句话说,这两个整数在内存中的地址不同。因此,修改一个并不修改另一个。传递的不是数组的地址,而是数组第一个元素的地址。(相同的内存地址,不同的类型。)例如,当我们使用数组[1]时,[1]是否已经隐式地取消了对指针的引用?此外,我尝试将数组初始化为int数组[3],并在函数头中的数组[3]中使用,但它仍然打印4 5 6,即使编译器可以保证按值传递所有内容所需的堆栈量。我错过什么了吗?谢谢大家!@Rogério,给定“int a[]={1,2,3}”,表达式a[1]正好等价于*(a+1)。也就是说,“a”是第一个int的地址,“a+1”是紧跟其后的int的地址,“*(a+1)”是该表达式指向的int。下标运算符可以看作是语法上的糖类。关于你的第二点,见我先前的评论。不能在C中按值传递数组。编译器是否有足够的信息来传递数组并不重要。我不是这么想的
mainArray = 0xbf806ad4, &mainArray[0] = 0xbf806ad4, mainArray[0] = 1
func1: dynArray = 0xbf806ad4, &dynArray[0] = 0xbf806ad4, dynArray[0] = 1
func2: intPtr = 0xbf806ad4, &intPtr[0] = 0xbf806ad4, intPtr[0] = 1
mainInt = 10, &mainInt = 0xbf806acc
func3: intVal = 10, &intValue = 0xbf806ad0