C和C ++中的可变长度数组(VLA)

时间:2012-12-28 20:13:30

标签: c++ c arrays variable-length-array

  

可能重复:
  Variably modified array at file scope

我有一些关于VLA及其行为的概念,我需要澄清。

AFIK自C99起,可以将VLA声明为本地范围:

int main(int argc, char **argv)
{
    // function 'main' scope
    int size = 100;
    int array[size];
    return 0;
}

但它在全球范围内被禁止:

const int global_size = 100;
int global_array[global_size]; // forbidden in C99, allowed in C++

int main(int argc, char **argv)
{
    int local_size = 100;
    int local_array[local_size];
    return 0;
}

上面的代码在C99中声明了一个VLA,因为const修饰符不会创建编译时值。在C ++中global_size是一个编译时值,因此,global_array不会成为VLA。

我需要知道的是:我的推理是否正确?我描述的行为是正确的吗?

我也想知道:为什么不允许全球范围内的VLA?在C和C ++中是否被禁止?数组在全局和局部范围内的行为有什么不同?

5 个答案:

答案 0 :(得分:5)

C ++不支持VLA,期间。第二个代码片段在C ++中工作的原因是const关键字在C ++中创建了一个编译时常量;在C中,它没有。

无论您如何声明大小变量,C99都不支持块范围,句点之外的VLA。请注意,C2011使VLA支持可选。

答案 1 :(得分:5)

是的,你的推理是正确的,这就是C和C ++如何查看这些不同形式的数组声明和定义。

正如其他人已经说过的那样,在全球范围内具有真实可变长度(非const)的VLA很难理解。评估顺序是什么,例如,如果长度表达式将引用不同编译单元的对象? C ++没有VLA,但它在文件范围内对对象进行动态初始化。如果你不得不依赖评估订单,这已经让你头脑疼痛了。

这为C留下了关于包含const限定对象的长度表达式的小间隙,这是不允许的。这是因为C标准不将这些对象视为“整数常量表达式”。这可能会在未来版本中发生变化,但到目前为止,C委员会认为没有必要允许这样的事情:有enum个常数在C中发挥作用。他们唯一的限制是他们是在C中限制为int,最好还有size_t

答案 2 :(得分:3)

我认为根本原因是全局变量具有链接,其大小必须在编译时知道。如果没有,怎么可以链接该程序?

局部变量没有链接,并且在堆栈上分配了VLA,它随着程序的运行而动态增长。

答案 3 :(得分:2)

被禁止和不被允许之间存在差异。 ; - )

VLA功能旨在允许为本地数组使用堆栈空间,以避免使用malloc进行堆分配。它主要是速度优化。

现在您想在函数之外使用VLA。为什么?在程序启动期间避免单个malloc调用的速度并不快。我们应该将哪些堆栈空间用于具有静态生命期的变量?

答案 4 :(得分:1)

因此,对于全球VLA来说,其中一个问题(主题有很多变种)可以在这里显示:

int size;
int a;
int v[size];
int b;

.... 在另一个文件中:

extern int a;
extern int b;

链接器必须在链接时知道a和a在哪里相互关联,否则它将无法在加载时正确修复它们。