Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
658 views
in Technique[技术] by (71.8m points)

c - How is the size of a variable length array computed at runtime in C99?

In C89, the length of an array is known at compile time. But in C99, with variable length arrays, the length of an array may be unknown before runtime.

So how does it get computed?

And why couldn't the length of a dynamically allocated array be computed in the same way?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

From ISO/IEC 9899:TC3 Section 6.7.5.2: Array declarators

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.

The sizeof a VLA is simply sizeof(vla_element_type) * vla_length. Since a VLA can only be defined within a block, its length must be either a local variable or a function parameter, which can be accessed by the compiler when the vla is accessed. (Since the length of vla and the vla itself belongs to the same stack frame).

Here is an example:

int main(int argc, char* argv[])
{
  int m;
  scanf("%d
", &m);
  int a[m];

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

  return 0;
}

Compiled with clang -o test.ll -O2 -emit-llvm -S test.c, the generated IR is shown as follows:

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
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...