sizeof运算符与变长数组一起作为函数参数

dtr*_*acy 2 c arrays gcc sizeof variable-length-array

根据GNU关于可变长度数组的文档,可以使用sizeof运算符来确定传递给函数的可变长度数组的大小:

您还可以使用可变长度数组作为函数的参数:

struct entry
tester (int len, char data[len][len])
{
  /* … */
}
Run Code Online (Sandbox Code Playgroud)

分配存储时计算一次数组的长度,并在您访问数组时记住该数组的范围sizeof.

但是,当使用下面的完整代码示例尝试此示例时,sizeof运算符将返回指针的大小,而不是基于上面的GNU代码段所预期的分配的vla的大小.

我知道在C中传递数组类似于将指针传递给数组的第一个元素,但由于我们在函数签名中指定了这种情况下的大小,我希望在使用sizeof范围时我可以模仿行为.声明数组的位置.

我也意识到我可以使用这个len参数来计算出尺寸; 但为了方便和理解GNU的实现,我仍然认为这是一个有趣的(如果不是很重要的)问题.

提前感谢任何能够深入了解此事的人!

// file: vla.c
#include <stdio.h>

void foo(int len, char data[len][len]) {
  printf("sizeof \"foo\" data: %lu\n", sizeof(data));
}

int main(int argc, char * argv[]) {
  char data[argc][argc];
  printf("sizeof \"main\" data: %lu\n", sizeof(data));
  foo(argc, data);
}
Run Code Online (Sandbox Code Playgroud)

编译使用:

gcc vla.c -o vla -std=c11
Run Code Online (Sandbox Code Playgroud)

叫做使用:

./vla 2 3 4 5
Run Code Online (Sandbox Code Playgroud)

输出:

sizeof "main" data: 25
sizeof "foo" data: 8
Run Code Online (Sandbox Code Playgroud)

分析:

main data有意义的大小; argc是5,因此它是一个(5*5 = 25)字节的2D数组.

foo data预计大小也是25,但是指针的大小.看起来编译器没有使用它知道data内部大小的事实,foo因为它是函数签名的一部分.

R..*_*R.. 5

声明的参数char data[len][len]确实char (*data)[len]是指向VLA的指针.没有实际的数组参数,len声明中的第一个是没有意义的.如果你使用sizeof *data,你会回来len,因为指向类型是可变的修改.

如果你想让两个lens 都有意义,你可以传递一个指向整个数组的指针,而不是指向第一个元素的指针,声明参数char (*data)[len][len].现在sizeof *data是len*len.但是您需要使用(*data)[i][j]它来访问它.&调用函数时,您还需要使用运算符:

int l = 42;
char array[l][l];
foo(l, &array);
Run Code Online (Sandbox Code Playgroud)