编译器在数组分配方面的不同行为

6

最近我发现了g++与MSVC++ 2008的一个有趣行为差异。考虑这个小程序:

#include <cstdlib>

const int ARR_LENGTH = 512;

void doSomething( int iLen );

int main( int argc, char** argv )
{
    doSomething( ARR_LENGTH );
    return 0;
}

void doSomething( int iLen )
{
    int iTest[iLen];
    return;
}

它会编译吗?你认为呢?根据我对C语言(或C ++)的了解,这应该不会编译,因为我可以使用任何整数调用函数doSomething(),所以不能在编译时确定iTest数组的大小。然而,当我尝试使用g++编译它时,它却可以正常工作。现在我可以理解这里可能发生了什么——编译器注意到我只调用了一次函数,并将编译时常量作为参数传递。这里进行了一些严格的优化...但是当我尝试使用MSVC++ 2008编译时,我得到了以下错误:

1>c:\prj\test\test.cpp(15) : error C2057: expected constant expression
1>c:\prj\test\test.cpp(15) : error C2466: cannot allocate an array of constant size 0
1>c:\prj\test\test.cpp(15) : error C2133: 'iTest' : unknown size

我的问题是:这是否符合语言的定义(C标准(C++标准))? g ++进行这种优化是否可以?(在这种情况下很容易看到,但第一次遇到它时,在一个大项目中,乍一看并不太合理)。

可能是在C++中使用可变长度数组?的重复问题。 - Ben Voigt
3个回答

5

C99(C标准的最新版本)允许使用动态大小数组。然而,这个特性不被Visual Studio支持(它只实现了C89支持)。

在C++中,这是无效的,也很可能永远无效。


为什么在C++中它永远不会有效?编译器只需要调整堆栈指针,使用默认构造函数初始化所有内容,并确保在作用域退出时进行清理,对吧?虽然不容易,但也不是不可能。这肯定比使用alloca()要好。 - Mike DeSimone
Jalf说:“可能永远不会有效”,而这个想法的一个很好的理由是C++委员会刚刚完成了下一个版本C++的标准编写,他们肯定考虑了C99中添加的所有功能,但可变长度数组并未被接受。请参见https://dev59.com/K3I-5IYBdhLWcg3wYXP8。 - Ben Voigt
1
正如@Ben所说,它被拒绝用于即将到来的C++0x,因此他们必须扭转这个决定才能以后添加它。在C++中,它并不像在C语言中那样必要。C++已经有了std::vector,可以解决许多相同的问题。在C++中,对VLA的需求就少了。 - jalf

2

动态大小数组是C99的一个特性。如果你的编译器支持C99(GCC支持,VC不完全支持),并且你使用了C99开关,那么这个代码就能编译通过。


0

这不是标准的C++(而是标准的C)。实现可能提供alloca(或msvc中的_alloca),它几乎可以完成工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接