2

以下 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;
}
4

4 回答 4

2

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

void foo(int (*b)[3])

也就是说,它接受一个指向三个整数数组的指针。考虑到这一点,让我们看看你的实现做了什么。首先,++b将指针前进以指向内存中的下一个3 个整数数组。也就是说,它前进b3 * sizeof(int). 对于您的程序,这意味着它指向a-{ 4, 5, 6 }行的“中间行”。

接下来,您访问[2][1]新的b. 也就是说,第二行,这个新的偏移逻辑数组的元素之一。这会导致您的程序写入 结束后的地址a,这是未定义的行为。在这个阶段,所有的赌注都被取消了。你的程序的输出可以是任何东西

您可以通过将该行更改为:

b[1][2] = 157;

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

于 2013-05-25T04:38:38.470 回答
0

编译器不会复制整个数组。如果它通过值传递如何传递一个包含 100000 个元素的数组。所以它作为“指针”传递。我猜该地址是作为副本传递的。所以改变地址的内容也会改变原来的东西。

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

于 2013-05-25T04:30:48.810 回答
0

根据:6.2.3.1/3 & 6.7.5.3/7

在对 foo 的调用中,数组表达式 arr 不是 sizeof 或 & 的操作数,它的类型根据 . 因此, foo 将接收一个指针值,而不是一个数组值。

所以当你这样做时:

 void foo(int b[][3])

它被隐式转换为:

 void foo((*b)[3])
于 2013-05-25T04:31:54.827 回答
-1

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

http://ideone.com/eWFxht

你当然需要重新检查你的输出。

于 2013-05-25T04:32:27.090 回答