C++编译器的差异(VS2008和g++)

6

我尝试在Linux和VS 2008中编译以下代码:

#include <iostream> //  this line has a ".h" string attached to the iostream string in the linux version of the code
using namespace std; // this line is commented in the linux version of the code
void main()
{

  int a=100;
  char arr[a];

  arr[0]='a';
  cout<<"array is:"<<arr[0];

}

这行代码在g++版本中可以正常工作,但在Visual Studio中不起作用。它会抛出以下错误:

1>c:\users\bibin\documents\visual studio 2008\projects\add\add\hello.cpp(7) : error C2057: expected constant expression
1>c:\users\bibin\documents\visual studio 2008\projects\add\add\hello.cpp(7) : error C2466: cannot allocate an array of constant size 0
1>c:\users\bibin\documents\visual studio 2008\projects\add\add\hello.cpp(7) : error C2133: 'arr' : unknown size

这是一个有效的语句吗?两个编译器怎么会对同一种语言有不同的解释呢?


1
你在Visual Studio中编译器的设置是什么?默认设置是Microsoft Visual C++。然而,GCC编译ISO C++。它们并不相同 - 在Microsoft对C++的实现中合法的一些东西,在ISO C++中可能不合法,反之亦然。 - Thomas Owens
@thomas:那么有没有办法将其更改为ISO C++设置?我希望为一个机器编写的代码可以在另一个机器上运行。至少不涉及系统调用的那些代码。 - tomkaith13
g++默认不使用ISO C++,而是使用带有GNU扩展的ISO。如果您想使用标准C ++,请使用-pedantic标志(然后VLA将在gcc上失败,因为它是非标准的)。要在Visual Studio中获得标准C ++,请避免任何名称中带有“CLR”的项目类型,并使用/Za选项禁用扩展。 - Steve Jessop
4个回答

14

这是C99的一个特性:

char arr[a]; // VLA: Variable Length Arrays (C99) but not C++!

GCC支持C99的许多特性,但VC不支持,我认为它在不久的将来也不会支持,因为他们越来越专注于C++。无论如何,你可以只是将声明改成:

  const int a=100; // OK the size is const now!
  char arr[a];

1
他们是在专注于C#吗? - Marcin Gil
4
不是用C++编译器,通常都使用Visual C++。C++分支于c89,因此C++编译器可以为传统的C代码提供C89模式,但支持C99则需要更多的工作量。 - MSalters
4
在我看来,C99的一些功能,比如可变长度数组(VLAs),不是标准C++甚至不是C++0x的一部分,因此微软没有支持它们是正确的。 - anon
请注意,MSVC的 _alloca 与glibc的 alloca 相当,因此您可以通过一些宏奇技来获得有效的跨平台替代品。不确定其他主要操作系统/体系结构上有什么可用的。 - Tom
值得一提的是,建议的解决方法(const int a)在VS2013中已经不再适用了。 :( - Per Lundberg
似乎在VS2012中也不行:http://stackoverflow.com/questions/13827599/oaidl-h319-error-c2057-expected-constant-expression - Per Lundberg

9

所有编译器在实现C++标准时都有微妙的差异。然而,你遇到的g++问题是因为默认情况下它启用了很多语言扩展。要获得有关这些警告,你应该始终至少使用-Wall和-pedantic标志进行编译:

g++ -Wall -pedantic myfile.cpp

这将会产生以下错误/警告:

myfile.cpp:1:119: error: iostream.h: No such file or directory
myfile.cpp:2: error: '::main' must return 'int'
myfile.cpp: In function 'int main()':
myfile.cpp:6: warning: ISO C++ forbids variable length array 'arr'
myfile.cpp:9: error: 'cout' was not declared in this scope

即使没有使用-Wall或者-pedantic选项,我也会收到一个警告,指出X.h头文件已经被弃用了。如果我使用<X>代替<X.h>,我将会得到cout未定义的错误,因为<X.h>版本使用了全局命名空间而不是std命名空间。 - Chris Huang-Leaver

3
尝试将int a更改为const int a。C++标准规定数组的大小应该是一个常量表达式。常量表达式的定义如下(5.19.1):
在多个地方,C++要求表达式评估为整数或枚举常量:作为数组边界(8.3.4、5.3.4)、作为case表达式(6.4.2)、作为位域长度(9.6)、作为枚举器初始化器(7.2)、作为静态成员初始化器(9.4.2)以及作为整数或枚举非类型模板参数(14.3)。常量表达式:条件表达式。整数常量表达式只能涉及文字(2.13)、枚举器、整数或枚举类型的const变量或静态数据成员,这些变量使用常量表达式初始化(8.5),整数或枚举类型的非类型模板参数,以及sizeof表达式。浮点文字(2.13.3)只能出现在它们被强制转换为整数或枚举类型时。只能使用整数或枚举类型的类型转换。特别地,在sizeof表达式中除外,不得使用函数、类对象、指针或引用,并且不得使用赋值、增量、减量、函数调用或逗号运算符。
根据此定义,int a = 100不是常量表达式。

1
在Microsoft C++中,在堆栈上创建大小无法在编译时确定的数组是无效的。您必须要么在堆上创建数组,要么使用常量来指定数组大小。
char *arr = new char[size];
const int size2 = 100;
char arr2[size2];

我认为这与微软无关。在标准C++中,这是不正确的。请参阅@Neil的答案,了解更多有关GCC允许此操作的详细信息。 - Khaled Alshaya

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