C99 在运行时如何计算可变长度数组的大小?

Posted

技术标签:

【中文标题】C99 在运行时如何计算可变长度数组的大小?【英文标题】:How is the size of a variable length array computed at runtime in C99? 【发布时间】:2012-12-04 05:02:35 【问题描述】:

在 C89 中,数组的长度在编译时是已知的。但是在 C99 中,对于可变长度数组,数组的长度在运行之前可能是未知的。

那么它是如何计算出来的呢?

为什么不能以同样的方式计算动态分配数组的长度?

【问题讨论】:

【参考方案1】:

VLA 和您通过指针变量持有的malloced 数组(除了位于内存的不同部分)之间的区别在于编译器在编译时知道第一个是数组。它可以与 VLA 一起在某个地方保存大小信息,所以基本上这是某种隐藏变量。根据您对该变量的使用情况,例如,如果您使用sizeof,或者如果您通过A[i][j] 之类的东西索引二维VLA,那么编译器可以决定是否真的需要该隐藏变量,如果不需要,优化一下。

【讨论】:

通俗易懂!谢谢。抱歉 11rep 我不能为你 +1。【参考方案2】:

来自 ISO/IEC 9899:TC3 第 6.7.5.2 节:数组声明符

具有可变修改类型的普通标识符(如 6.2.3 中定义)应具有 块范围,没有链接或函数原型范围。如果声明了标识符 为静态存储时长的对象,不能为变长数组类型。

VLA 的大小只是sizeof(vla_element_type) * vla_length。由于 VLA 只能在块内定义,its length must be either a local variable or a function parameter,在访问 vla 时编译器可以访问该块。 (由于vla的长度和vla本身属于同一个栈帧)。

Here is an example:

int main(int argc, char* argv[])

  int m;
  scanf("%d\n", &m);
  int a[m];

  printf("%d\n", sizeof(a));

  return 0;

clang -o test.ll -O2 -emit-llvm -S test.c编译,生成的IR如下图:

define i32 @main(i32 %argc, i8** nocapture %argv) nounwind 
entry:
  // Allocate space on stack for m
  %m = alloca i32, align 4  

  // call scanf
  %call = call i32 (i8*, ...)* @__isoc99_scanf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i32* %m) nounwind  

  // %0 now contains the value of m
  %0 = load i32* %m, align 4, !tbaa !0

  // %1 is m << 2, which is m * sizeof(int)
  %1 = shl nuw i32 %0, 2  

  // call printf, output m * sizeof(int) to screen.
  %call1 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i32 0, i32 0), i32 %1) nounwind  

  // DONE.
  ret i32 0

【讨论】:

是否可以像这样定义一个函数:foo(int array[size], int size),以便我可以使用sizeof(array) 来计算该函数内array 的大小? 不,这是不可能的。数组参数将被编译器转换为指针。也请看看这篇文章:***.com/questions/5493281/c-sizeof-a-passed-array 好的,这里是 GCC/CLANG n00b:什么是 IR? IR 表示中间表示:en.wikipedia.org/wiki/…

以上是关于C99 在运行时如何计算可变长度数组的大小?的主要内容,如果未能解决你的问题,请参考以下文章

在标准 C 中(不在 C99 中)在运行时声明数组的大小

如何在编译时获取数组大小?

使用可变长度数组是不是有任何开销?

更改1D和2D可变长度数组的大小

具有可变长度数组类型的 Sizeof 运算符

分配数组 VS。可变长度数组[重复]