最近,我正在调试我的一个程序并发现了一个我经常犯的错误,但在编译过程中没有显示为警告,所以我只是假设一切都已就绪并且没问题。我对以下代码中发生的事情感到困惑:
void foo(char b[2]);
char a[2] = {1, 2};
foo(a); // I always assumed that this would pass the entire array to be
// duplicate in stack, guess I was wrong all this while
// Instead the address of the array was passed
void foo(char b[2])
{
// Value of b[0], b[1]?
// Does this mean : 1) b[0] == &a[0]?
// or 2) b[0] == &a[0+2]?
// Compiler didn't complain, so I assume this is a valid syntax
}
答案 0 :(得分:6)
当您将数组作为参数传递给函数时,它会衰减为指针,这在6.7.1
中的C标准中定义:
在进入函数时,每个参数表达式的值应转换为类型 它的相应参数,就像通过赋值给参数一样。 数组表达式和 函数指示符作为参数在调用之前被转换为指针。宣言 “类型数组”的参数应调整为“指向类型的指针,”
这实质上意味着在你的函数声明中它等同于使用
void foo(char b[2]);
或
void foo(char b[]);
或
void foo(char *b)
`
答案 1 :(得分:0)
这是有效的语法,是的,当传递数组时,第一个元素的内存地址被复制,但是当你取消引用地址时,你正在修改原始数组。
答案 2 :(得分:0)
这与以下内容相同:
// The array "char b[2]" "decays" to a pointer "char *b"
void foo(char *b)
{
// b[0] == a[0]
// also, b == a (two addresses, both the same)
}
您可以了解C中的数组和指针的行为方式非常相似(但 完全相同)。如果它们是函数参数(但不是其他任何地方),则数组会衰减为指针。这里真正的问题是在64位系统上sizeof(b) == 8
和sizeof(a) == 2
,除非你知道数组衰减为指针,否则这有点令人惊讶。
答案 3 :(得分:0)
将数组声明为函数参数时,会将其视为指针。您的foo
与
void foo(char *b)
{
...
}
数组衰减到指针。换句话说,在某些用途中(例如sizeof(a)
)a
是一个数组,但在其他需要指针的地方,名称a
表示地址a[0]
。
答案 4 :(得分:0)
b[0] = &a[0]
作为参数,则 foo(a)
。
如果您通过foo((a+1))
然后b[0] = &a[1]
(您不应该这样做,因为b[1]
未定义)等等。
答案 5 :(得分:0)
我应该做一个修正:数组的地址没有传递 - 它是数组第一个元素的地址。最简单的方法是:
在C中,数组的值是指向其第一个元素的指针。
如果使用数组数组,则需要在第一次取消引用后提供有关数组大小的信息:
// either the following or: void foo(char param[][30][20])
void foo(char (*param)[30][20])
{
// ...
}
int main(void)
{
// bar is an array of 10 arrays of 30 arrays of 20 chars.
// its value's TYPE is 'pointer to an array of 30 arrays of 20 chars,
// which is what foo above requires.
char bar[10][30][20];
foo(bar);
}