1

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

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

使用 option -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而另一个包含 header complex.h

4

2 回答 2

2

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

作为扩展,<complex.h> 的 C++ 版本包括 C 版本,但它定义了具有不应在 ISO C++ 中定义的非保留名称的宏。仅包含用于非严格模式或 C++11 之前的 C 标头(因为 C++98 根本没有提及 <complex.h>)。

于 2021-08-26T09:36:38.770 回答
1

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

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

diff文件。

根本原因是,仅在未设置/usr/include/complex.h时才获取文件__STRICT_ANSI__。通过使用 gnu 扩展,未设置此宏。您可以在文件中看到选择/usr/include/c++/11/complex.h

您的头文件的安装路径可能会有所不同,但我相信您可以将给定的信息与您的库安装相匹配。

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

很清楚,如果I定义为“某物”,您的代码将停止运行,并会导致任何不是有效变量名的东西。

于 2021-08-26T09:36:31.170 回答