C 将参数传递给函数

C 将参数传递给函数,c,parameter-passing,C,Parameter Passing,以下ode段的输出为9。我认为函数foo的参数a是通过值传递的。我的假设正确吗。如果是这样,输出如何变为9 #include <stdio.h> void foo(int[][3]); int main(void) { int a[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }; foo(a); printf("%d\n", a[2][1]); return 0; } void foo(int b[][3])

以下ode段的输出为9。我认为函数foo的参数a是通过值传递的。我的假设正确吗。如果是这样,输出如何变为9

 #include <stdio.h>

void foo(int[][3]);

int main(void)
{
   int a[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };

   foo(a);
   printf("%d\n", a[2][1]);

   return 0;
}

void foo(int b[][3])
{
   ++b;
   b[1][1] = 9;
}
#包括
void foo(int[][3]);
内部主(空)
{
INTA[3][3]={{1,2,3},{4,5,6},{7,8,9};
傅(甲),;
printf(“%d\n”,a[2][1]);
返回0;
}
void foo(int b[][3])
{
++b;
b[1][1]=9;
}

编译器不会复制整个数组。如果它的pass-by值为,那么传递一个100000个元素的数组怎么样。因此它被传递为“指针”。我想这个地址是作为副本传递的。所以改变地址的内容也会改变原来的东西


似乎是通过指针传递引用。

根据:6.2.3.1/3和6.7.5.3/7

在对foo的调用中,数组表达式arr不是sizeof或&的操作数,它的类型根据类型从“int数组”隐式转换为“指向int的指针”。因此,foo将接收指针值,而不是数组值

所以当你这样做的时候:

 void foo(int b[][3])
它被隐式转换为:

 void foo((*b)[3])

你的程序的输出如预期的那样是8。这里没有什么意外。你在
b[2][1]=9
中所做的是在
b
递增后将9写入位置
a[3][1]
。这不会影响
a[2][1]的输出
在调用
foo()前后保持8


您当然需要重新检查输出。

函数参数类型的
[]
语法只是语法上的糖分。在这种情况下传递指针,就像在函数调用上下文中使用数组一样。这意味着您的
foo()
函数的签名等效于:

void foo(int (*b)[3])
也就是说,它接受指向三个整数数组的指针。考虑到这一点,让我们看看您的实现是做什么的。首先,
++b
将指针向前移动,指向内存中下一个由3个整数组成的数组。也就是说,它将
b
前进
3*sizeof(int)
。在您的程序中,这意味着它指向
a
的“中间行”——
{4,5,6}

接下来,访问新
b
的元素
[2][1]
。也就是说,第二行,这个新偏移量逻辑数组的元素1。这会导致程序写入超过
a
结尾的地址,这是未定义的行为。在这个阶段,所有的赌注都没有了。程序的输出可以是任何内容

通过将该行更改为:

b[1][2] = 157;

比如说。然后,打印
a[2][2]
以查看
main()
函数上下文中的更改。

在C中,数组从不按值传递——类型为“array of T”的参数被调整为“指向T的指针”。我运行代码,它给我8!哇,很多错误的答案。请不要用断章取义的方式编辑你的问题。不完全是这样。它会被转换为
int(*b)[3]
。您的编辑可以在某种程度上改善情况。您现在缺少一个类型。此答案最接近正确,但将9写入
a[3][1]
是未定义的行为。在这种情况下,OP的程序可以输出9,尽管我很难找到一个好的解释来解释为什么会发生这种情况。你怎么知道这些事情?根据ABI,堆栈上可能不会有任何东西被推送。你到底在问什么?可以在C中按值传递数组吗?不,不能在C中按值传递数组。不过,你可以使用一些技巧,比如将数组放入结构中,然后按值传递结构。