Ответ 1
Из ИСО/МЭК 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
}