2011-04-20 26 views
4

我不是一个C++专家,但据我所知,这个码应该会由于size不固定:什么时候变长数组合法?

#include<iostream> 

using namespace std; 

int main(int argc, char** argv) 
{ 
    int size = *argv[1] - 48; 
    char array [size]; 
    cout<<sizeof(array)<<endl; 

    return 0; 
} 

为什么这个工作时,我编译与海湾合作委员会(最好说G ++)?

./test 7 
7 
/test 2 
2 

回答

1

这是一个C99功能,允许您在堆栈中声明类似的数组。

2

这是一个非标准的GCC扩展 - 其他编译器如Visual C++不支持。

0

即使没有VLA扩展,代码也可以在编译器未能推导出维度表达式在编译时不为人知的情况下进行编译。它仍然是UB。

0

因为您没有将g ++作为C++编译器调用。如果我尝试它,我会收到警告,明确指出“ISO C++禁止可变长度数组”。但是我的makefile包括选项-std=c++98,至少当我想编译可移植的C++时。

3

这是一个list of new features in C99其中增加了variable length arrays

另见$ 6.7.6.2/4 数组声明N1548ISO/IEC 9899:201X委员会草案 - 2010年12月2日N1548),详细了。

+1

*但*:没有C++标准曾接受过C99的VLA,因此从技术上讲,在C++中接纳VLA的事实是'g ++'扩展。 – 2012-07-28 01:45:31

5

要从堆栈或堆中为变量分配内存,变量的大小需要知道。 C++编译器可以自己决定如何分配内存,但是C++已经公开了他们希望C++编译器如何处理这种情况,因此C++ std要求编译器供应商发布他们的内存处理。这是通过sizeof运算符发生的。该运算符在编译时完全计算。数组大小的编译时间限制来自此要求。

int arr[10]; 
std::cout << sizeof(arr) << std::endl 

因为每个变量和类型都支持sizeof,所以它们的大小需要在编译时在C++中计算。因此,变长数组在C++中是不可能的。

这个要求还有另一个非常重要的限制。原则上,C++编译器供应商可以计算C++程序堆栈所需的最大内存量(如果没有问题的话):对于递归函数,不能计算程序使用的堆栈大小,但对于其他任何情况,堆栈大小都可以通过执行以下操作来计算:

  1. 使用sizeof(a)用于在堆栈帧
  2. 总和的每个变量的变量的尺寸,以获取该堆栈帧
  3. 列表中的所有可能的堆栈所需的存储器量帧并计算其大小
  4. 挑选最大尺寸的调用堆栈
  5. 选择该大小作为程序堆栈的大小。

不幸的是,递归函数打破了整个方案。而且它需要全局程序的流程分析来重新识别哪些函数可能具有无限的调用堆栈。但是编译时sizeof运算符的限制很重要,否则我们的C++程序会随机用尽堆栈空间,导致崩溃和不稳定。这是不可接受的。因此每个变量和类型都支持编译时sizeof运算符。

VLA支持要求编译器可以生成代码,其中通常生成的偏移量作为结果机器代码的常量在运行时实际上是可修改的。符合标准的C++编译器通常无法做到这一点。 C决定添加这个支持,因此C编译器可以做到这一点。但在这个过程中,他们需要打破运营商规模。编译时不再可以计算大小。如在C标准中规定的VLA的支持有很大的问题:

  1. 你不能把VLA结构或类中
  2. VLA的基本上仅限于本地函数范围

这些问题已经解决在C++中通过std :: vector没有任何这些问题。

1

c99支持可变长度数组(VLA),但既不c90也不C++支持可变长度数组,但是gcc支持此作为an extension in both C and C++你可以看到这更清楚地,如果你有这些参数编译:

gcc -std=c89 -pedantic 

这将给你以下警告:

warning: ISO C90 forbids variable length array ‘array’ [-Wvla] 

g++

g++ -pedantic 

会给你这样的警告:

warning: ISO C++ forbids variable length array ‘array’ [-Wvla] 

gcc手册此standards节进入更多的细节。重要的是要注意,截至2011年C标准可变长度阵列(VLA)现在是可选的。