向函数传递参数

问题描述 投票:0回答:4

下面的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;
}
c parameter-passing
4个回答
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()
函数上下文中的变化。


0
投票

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

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


0
投票

根据: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])

-1
投票

您的程序的输出是 8 正如预期的那样。这里没有什么意外的。在

b[2][1] = 9
中,增加
b
后,您将 9 写入位置
a[3][1]
。它不会影响
a[2][1]
的输出,在调用 foo() 之前和之后仍保持
8

http://ideone.com/eWFxht

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

© www.soinside.com 2019 - 2024. All rights reserved.