在C89,阵列的长度在编译时是已知的。 但是,在C99,与可变长度数组,一个数组的长度可以是运行时之前未知的。
那么它是如何获得计算的?
为什么不能动态分配的数组的长度以同样的方式计算的?
在C89,阵列的长度在编译时是已知的。 但是,在C99,与可变长度数组,一个数组的长度可以是运行时之前未知的。
那么它是如何获得计算的?
为什么不能动态分配的数组的长度以同样的方式计算的?
从ISO / IEC 9899:TC3第6.7.5.2:数组声明
具有可变类型的普通标识符(如在6.2.3中定义的) 应具有任一块范围和没有键或函数原型范围。 如果一个标识符被声明为具有静态存储持续时间的对象,应当不具有可变长度数组类型。
sizeof运算一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
}
VL A和之间的差malloc
您通过指针变量(除了生活在存储器的不同部分)保持ED阵列是编译器在编译时知道第一是一个数组。 它可以与VLA一起抱在一些地方的大小信息(S),所以基本上这是某种形式的隐变量(一个或多个)的。 根据您与该变量做使用,如果如您使用sizeof
用它,或者如果你指数2D VLA通过类似A[i][j]
编译器可以再决定是否真的需要隐藏的变量,并且,如果不是,优化出来。