在C中通过引用传递数组

我是C的新手,我有一个疑问。

由于C函数创建了它的参数的本地副本,我想知道为什么下面的代码按预期工作:

void function(int array[]){ array[0] = 4; array[1] = 5; array[2] = 6; } int main(){ int array[] = {1,2,3}; function(array); printf("%d %d %d",array[0],array[1],array[2]); return 0; } 

线路输出为4 5 6。

为什么这样做有效而以下情况不然?

 void function(int integer){ integer = 2; } int main(){ int integer = 1; function(integer); printf("%d",integer); return 0; } 

在这种情况下,输出仅为1。

简短版本:为什么函数可以修改父变量的值,如果它们作为数组传递?

谢谢你们!

这是因为数组倾向于衰减为指针。

 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 

ap将打印相同的值。

与其他人所说的相反, a 不是指针,它可以简单地衰减为1。 http://c-faq.com/aryptr/aryptrequiv.html

在你的第一个function()传递的是数组的第一个元素的地址,函数体取消引用它。 事实上,编译器正在将函数原型视为:

 void function(int* array /*you wrote int array[]*/){ array[0] = 4; array[1] = 5; array[2] = 6; } function(&array[0]); 

这必须发生,因为你说“未知大小的数组”(int array [])。 编译器无法保证推导出值传递所需的堆栈量,因此它会衰减到指针。

—-编辑—-

让我们结合你的例子,并使用更多独特的名称,使事情更清晰。

 #include  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; } 

在ideone上进行现场演示: http ://ideone.com/P8C1f4

 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 

func1func2 “dynArray”和“intPtr”是局部变量,但它们是指针变量,它们从main接收“mainArray”的地址。

此行为特定于数组。 如果要将数组放在结构中,那么您可以按值传递它。

传递给函数的数组将转换为指针 。 将指针作为参数传递给函数时,只需在内存中提供变量的地址即可。 因此,当您修改数组单元格的值时,可以编辑给定函数的地址下的值。

将简单整数传递给函数时,整数将复制到堆栈中,当您修改函数内的整数时,修改整数的副本,而不是原始的副本。

提醒C中的各种内存

在C中,我们可以使用三种类型的内存:

  • 堆栈,用于局部变量和函数调用 :当我们在main()中创建变量时,我们使用堆栈来存储变量,并且当调用函数时,给予方法的参数在堆栈中注册。 当我们退出一个函数时,我们“弹出”这些参数以返回到原始状态,在调用函数之前使用used变量。 (轶事:stackoverflow是指当我们破解堆栈以使用函数中的先前变量而不将其作为参数传递时)
  • 与动态分配的内存对应的堆 :当我们需要大量数据时,我们使用此堆,因为堆栈限制为几兆字节。
  • 存储程序指令的代码

如果这个数组由一个函数传递,它是一个指针(另一个变量的地址),它存储在堆栈中,当我们调用该函数时,我们将指针复制到堆栈中。

在整数的情况下,它也存储在堆栈中,当我们调用函数时,我们复制整数。

如果我们想修改整数,我们可以传递整数的地址来修改指针下的值,如下所示:

 void function(int *integer) { *integer = 2; } int main() { int integer = 1; function(&integer); printf("%d", integer); return 0; } 

“按引用传递”和“按值传递”之间存在差异

通过引用传递引导到内存中的位置,其中pass by value直接传递值,数组变量始终是refference,因此它指向内存中的位置。 默认情况下,整数将按值传递

在第一个代码中,您传递的数组的地址指向数组中的顶部元素。 因此,当您修改函数中的值并返回到main函数时,您仍然访问位于同一地址的同一个数组。 这称为通过引用传递。

但是,在第二种情况下,整数的值从main函数复制到被调用函数。 换句话说,两个整数在存储器中处于不同的地址。 因此修改一个不会修改另一个。

数组名称是指向数组中第一个元素的指针。 在第一个代码示例中,您已经传递了一个指向包含第一个数组元素的内存位置的指针。 在第二个代码示例中,您按值传递了一个整数,因此它与名为“integer”的局部变量无关

检查该链接

通过引用传递并通过值传递

在C ++中通过引用/值传递