【问题标题】:sizeof operator in conjunction with variable-length array as function argumentssizeof 运算符与可变长度数组一起作为函数参数
【发布时间】:2019-01-10 22:10:54
【问题描述】:

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

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

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

数组的长度在分配存储时计算一次,并记住数组的范围,以防您使用sizeof 访问它。

但是,当使用下面的完整代码示例尝试此示例时,sizeof 运算符返回指针的大小,不是分配的 vla 的大小,正如基于 GNU 的预期上面的sn-p。

我知道在 C 中传递数组类似于传递指向数组第一个元素的指针,但是由于我们在这种情况下在函数签名中指定了大小,所以我希望在使用 @ 时会模仿这种行为987654325@在声明数组的范围内。

我也意识到我可以使用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);
}

编译使用:

gcc vla.c -o vla -std=c11

调用使用:

./vla 2 3 4 5

输出:

sizeof "main" data: 25
sizeof "foo" data: 8

分析:

maindata 的大小有意义; argc 是 5,因此它是一个 (5 * 5 = 25) 字节的二维数组。

foodata 的大小预计也是 25,但实际上是指针的大小。似乎编译器没有使用它知道datafoo 中的大小这一事实,因为它是函数签名的一部分。

【问题讨论】:

  • 我怀疑你会发现正常的规则适用于函数参数(你得到一个指针的大小)。您引用的文本主要指的是在函数内部定义的数组(您不能在全局范围内定义可变大小的数组)。话虽如此,手册参考肯定意味着您正在做的事情应该有效。
  • 旁白:最好将"%zu"size_t 一起使用--> printf("%zu\n", sizeof(...));
  • 经过一番疯狂的思考,我认为调用函数时没有分配存储空间。我认为示例代码之后的段落是不合理的。但从手册上看并不明显。
  • @JonathanLeffler,我同意这个评估。也感谢您的格式修复,非常感谢!

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


【解决方案1】:

声明为char data[len][len] 的参数实际上是char (*data)[len],一个指向VLA 的指针。没有真正的数组参数这样的东西,声明中的第一个len 是没有意义的。如果你使用sizeof *data,你会得到len,因为指向的类型是可变修改的。

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

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

【讨论】:

  • 应该注意the page OP refers to 写得不好。它说“您也可以使用可变长度数组作为函数的参数”,并给出了声明为 char data[len][len] 的参数示例。这在技术上可能是正确的,因为数组可以“用作”该函数的参数,但它仍然被转换为指针,并且措辞具有误导性,可能表明 GCC 支持某些 C 扩展或偏差……
  • ... char data[len][len] 类型可能是为了表明第二维是可变长度的。措辞应该是说可变长度数组可以用作传递给函数的类型的一部分,例如char (*data)[len]
猜你喜欢
  • 2018-07-17
  • 2015-12-18
  • 2015-11-12
  • 2015-05-04
  • 2020-07-28
  • 1970-01-01
  • 2013-02-06
  • 1970-01-01
相关资源
最近更新 更多