【问题标题】:gcc option std=gnu++17 vs std=c++17gcc 选项 std=gnu++17 与 std=c++17
【发布时间】:2021-10-26 07:23:20
【问题描述】:

我在使用带有-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

【问题讨论】:

  • 对于 std=gnu++17,标识符 I 为库保留。不要使用std=gnu++17

标签: c++ gcc compiler-errors


【解决方案1】:

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

C++ 头文件 &lt;ccomplex&gt; (D.4.1) 和 &lt;ctgmath&gt; (D.4.4),以及它们对应的 C 头文件 &lt;complex.h&gt;&lt;tgmath.h&gt;,不包含任何来自 C 标准库的内容,而是 仅包含来自 C++ 标准库的其他头文件。

所以 C 的 complex.h 不包含在 C++ 中,这意味着在您的代码中 I 不应定义为任何内容。

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

作为扩展, 的 C++ 版本包括 C 版本, 但这定义了具有不应该被保留的名称的宏 在 ISO C++ 中定义。仅包含非严格模式的 C 标头,或 对于 C++11 之前的版本(因为 C++98 根本没有提到 )。

【讨论】:

    【解决方案2】:

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

     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 被定义为“某物”,您的代码将停止运行,并会导致任何不是有效变量名的东西。

    【讨论】:

    • 也是一个非常有用的答案,我想知道cmake会自动选择std=gnu++17,但这当然是一个不同的问题。
    猜你喜欢
    • 2019-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 2017-12-11
    • 2019-06-13
    • 2018-07-28
    相关资源
    最近更新 更多