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

标签 c arrays c99 variable-length-array ansi-c

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

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

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

最佳答案

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

An ordinary identifier (as defined in 6.2.3) that has a variably modified type shall have either block scope and no linkage or function prototype scope. If an identifier is declared to be an object with static storage duration, it shall not have a variable length array type.

VLA 的大小就是sizeof(vla_element_type) * vla_length。由于 VLA 只能在 block 内定义,它的长度必须是局部变量或函数参数,在访问 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
}

关于c - 在 C99 中如何在运行时计算可变长度数组的大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13908421/

相关文章:

c - 在 C 结构体中存储字符串

c - 无法初始化二维数组

javascript - Javascript "multi-dimensional arrays"的奇怪问题(即数组的数组)

c - 指向整数并再次返回的指针

c - 变量改变的位置?

c - 数据记录大小的估计

c - 当我用printf删除不相关的句子时,我的程序将无法正常运行

arrays - SwiftUI 从列表中删除行

C 风格编码和动态数组

c - 使用 write 函数将 double 写入标准输出