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

4

最近,我在调试一个程序时发现了一个经常犯的错误,但在编译过程中并没有显示为警告,因此我一直认为一切都很顺利,没问题。我对下面的代码有点困惑:

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
当您将数组作为参数传递给函数时,它会衰变为指针。这在C标准中有定义,在6.7.1中说明:
“进入函数时,每个参数表达式的值都应转换为其相应参数的类型,就像通过赋值给参数一样。调用之前,数组表达式和函数设计符作为参数被转换为指针。”
这基本上意味着在函数声明中使用以下任何一种方式是等效的:
void foo(char b[2]); void foo(char b[]); void foo(char *b)

对于foo(char b[2]),这是否意味着我只能访问长度为2的数组,例如b[0],b[1]是有效的,但不包括b[2]等? - freonix
4
不,你放在括号里的实际值没有任何相关性。 - lccarrasco
2
更明确地说,您可以使用任何大小的字符数组调用f,并且在f内部,您可以访问数组中的所有有效位置而不会出现问题。但是,如果您尝试访问超出实际数组大小的位置,则会导致未定义行为,这意味着任何事情都可能发生。 - lccarrasco

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) == 8sizeof(a) == 2,这有点出人意料,除非你知道数组会衰变成指针。

0
  1. 当您将数组声明为函数参数时,它会被视为指针。您的 foo 与下面的代码完全相同:

    void foo(char *b)
    {
        ...
    }
    
  2. 数组会衰变成指针。换句话说,在某些用法中(例如 sizeof(a)),a 是一个数组,而在其他需要指针的情况下,名称 a 意味着 a[0] 的地址。


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

}

0

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


0

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接