如何可变长度数组的大小在C99在运行时计算? [英] How is the size of a variable length array computed at runtime in C99?

查看:446
本文介绍了如何可变长度数组的大小在C99在运行时计算?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C89中,数组的长度是在编译时已知。但在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?

推荐答案

从ISO / IEC 9899:TC3第6.7.5.2:数组声明

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

这有一个可变类型的一个普通的标识符(如6.2.3定义)应具有
  无论是块范围和没有任何联系或函数原型范围。
如果一个标识符声明
  要与静态存储持续时间对象,不得具有可变长度数组类型。

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.

sizeof运算一个VLA简直是的sizeof(vla_element_type)* vla_length 。由于VLA只能在块内进行定义,其长度必须是本地变量或函数参数,它可以由编译器在VLA被访问来访问。 (由于VLA的长度和本身属于相同的堆栈帧的VLA)。

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\n", &m);
  int a[m];

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

  return 0;
}

编译时铛-o test.ll -O2 -emit-LLVM -S test.c的,生成的IR如下所示:

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
}

这篇关于如何可变长度数组的大小在C99在运行时计算?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆