gcc option std=gnu++17 vs std=c++17



我在-std=gnu++17中使用g++(我尝试了版本8到11)时遇到了编译错误,但是使用选项-std=c++17可以编译相同的代码。

#include <complex.h>
int main()
{
int I=0;
return I;
}

选项-std=gnu++17,这会导致以下错误:

error: invalid cast from type '__complex__ float' to type 'int'
5 |     int I=0;

使用-std=c++17选项,编译时没有警告和错误。

我知道在complex.h头中有一个宏定义#define I _Complex_I。gcc文档说-std=gnu++17选项添加了相应c++标准的GNU方言。但是,我不明白为什么这会导致上述程序的编译不同。

背景:当我开始使用cmake功能cxx_std_17时,我遇到了这种行为,该功能添加了标志std=gnu++17,并导致各种编译错误,因为一个第三方库使用标识符I,另一个库包含头complex.h

c++标准说:(c++ 17 C.6.1/3):

c++头文件<ccomplex>(D.4.1)和<ctgmath>(D.4.4),以及它们对应的C头文件<complex.h><tgmath.h>不包含任何来自C标准库的内容仅包括c++标准库中的其他头文件。

所以C的complex.h不包含在c++中,这意味着在你的代码中I不应该被定义为任何东西。

当允许GNU扩展时,GCC确实包含C内容作为扩展。见PR 82417:

作为包括C版本,但是这定义了不应该使用非保留名称的宏在ISO c++中定义的。只包含非严格模式的C头文件,或者c++ 11之前版本(因为c++ 98没有提到) .

您可以通过简单地从具有不同标准设置的预处理器中获取结果来自己找出差异,如下所示:

g++ -std=gnu++17 main.cpp -E > gnu
g++ -std=c++17 main.cpp -E > std

diff文件。

潜在的原因是,只有当__STRICT_ANSI__没有设置时,文件/usr/include/complex.h才会被占用。通过使用gnu扩展,这个宏不会被设置。您可以在文件/usr/include/c++/11/complex.h

中看到选区头文件的安装路径可能不同,但我相信您可以将给定的信息与您的库安装相匹配。

一般来说,I不应该在c++中定义,但如果使用gnu扩展则应该定义。提示是:不要使用这样的扩展,因为它们可能使您的代码与其他编译器不兼容。

很明显,如果I被定义为"something"并将导致任何不是有效变量名的内容。

最新更新