将数组地址作为函数参数传递

最近,我正在调试我的一个程序并发现了一个我经常犯的错误,但在编译过程中没有显示出警告,所以我只是假设一切都已到位并且没问题。 我对以下代码中发生的事情感到困惑:

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 } 

将数组作为参数传递给函数时,它会衰减为指针,这在6.7.1中的C标准中定义:

在进入函数时,每个参数表达式的值应转换为其相应参数的类型,就像通过赋值给参数一样。 数组表达式和函数指示符作为参数在调用之前转换为指针 。 参数声明为“类型数组”应调整为“指向类型的指针 ”,

这实际上意味着在你的函数声明中它等同于使用

void foo(char b[2]); 或者void foo(char b[]); 或者void foo(char *b)

`

它是有效的语法,是的,当传递数组时,第一个元素的内存地址被复制,但是当你取消引用地址时,你正在修改原始数组。

这与以下内容相同:

 // 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) == 8sizeof(a) == 2 ,这有点令人惊讶,除非你知道数组衰减为指针。

  1. 将数组声明为函数参数时,将其视为指针。 你的foo完全相同

     void foo(char *b) { ... } 
  2. 数组衰减到指针。 换句话说,在某些用途中(例如sizeof(a)a是一个数组,但在其他需要指针的地方,名称a 表示 a[0]的地址。

b[0] = &a[0]如果你做foo(a)作为参数。

如果你传递foo((a+1))然后b[0] = &a[1] (你不应该这样做,因为b[1]将是未定义的),依此类推。

我应该进行更正:数组的地址没有传递 – 它是数组第一个元素的地址。 最简单的方法是:

在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); }