sizeof运算符结合可变长度数组作为函数参数

时间:2018-08-03 04:43:34

标签: c arrays gcc sizeof variable-length-array

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

  

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

struct entry
tester (int len, char data[len][len])
{
  /* … */
}
     

分配存储空间后,将计算一次数组的长度,并记住该数组的范围,以防您用sizeof访问它。

但是,当使用下面的完整代码示例尝试该示例时,sizeof运算符会返回指针的大小,不是,这是基于上面的GNU代码段。

我知道在C中传递数组类似于传递指向数组第一个元素的指针,但是由于在这种情况下我们在函数签名中指定了大小,因此我希望使用{ {1}}在声明数组的范围内。

我还意识到我可以使用sizeof参数来确定大小;但是为了方便和理解GNU实现,我仍然认为这是一个有趣的(即使不重要的)问题。

在此先感谢您提供任何见解的人!

len

编译使用:

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

使用以下方式致电:

gcc vla.c -o vla -std=c11

输出:

./vla 2 3 4 5

分析:

sizeof "main" data: 25 sizeof "foo" data: 8 main的大小是合理的; data是5,因此它是(5 * 5 = 25)字节的2D数组。

argc foo的大小也应为25,但指针的大小应为25。似乎编译器没有使用它知道datadata的大小这一事实,因为它是函数签名的一部分。

1 个答案:

答案 0 :(得分:5)

声明为char data[len][len]的参数实际上是char (*data)[len],是指向VLA的指针。没有实际的数组参数,声明中的第一个len是没有意义的。如果您使用sizeof *data,则由于指向类型是可变地修改的,因此您将返回len

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

int l = 42;
char array[l][l];
foo(l, &array);