以下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;
}
答案 0 :(得分:2)
函数参数类型的[]
语法只是语法糖。在这种情况下传递指针,就像在函数调用上下文中使用任何其他数组一样。这意味着您的foo()
函数的签名等同于:
void foo(int (*b)[3])
也就是说,它接受一个指向三个整数数组的指针。考虑到这一点,让我们来看看你的实现是做什么的。首先,++b
使指针前进,指向内存中3个整数的 next 数组。也就是说,它会b
提前3 * sizeof(int)
。对于您的程序,这意味着它指向a
- { 4, 5, 6 }
行的“中间行”。
接下来,您可以访问新[2][1]
的元素b
。也就是说,第二行,这个新的偏移逻辑数组的元素之一。这会导致程序写入a
结尾的地址,这是未定义的行为。在这个阶段,所有赌注都已关闭。您的程序输出可能是任何。
您可以通过将该行更改为:
来恢复已定义的行为b[1][2] = 157;
例如,。然后,打印a[2][2]
以查看main()
功能的上下文中的更改。
答案 1 :(得分:0)
编译器不会复制整个数组。如果它传递值如何传递100000个元素的数组。所以它作为“指针”传递。我猜这个地址是作为副本传递的。所以改变地址的内容也会改变原来的东西。
似乎通过指针传递引用。
答案 2 :(得分:0)
根据:6.2.3.1/3&amp; 6.7.5.3/7
在对foo的调用中,数组表达式arr不是sizeof或&amp;的操作数,其类型根据“隐式”从“array of int”转换为“指向int的指针”。因此,foo将接收指针值,而不是数组值。
所以当你这样做时:
void foo(int b[][3])
它被隐式转换为:
void foo((*b)[3])
答案 3 :(得分:-1)
您的程序输出 8 符合预期。此处没有任何意外。在递增b[2][1]=9
之后您在b
做的是写 9 到位置a[3][1]
。在您致电a[2][1]
之前和之后,它不会影响foo()
的输出 8 。
您当然需要重新检查输出。