ChatGPT解决这个技术问题 Extra ChatGPT

在 GCC/G++ 编译器中使用 -pedantic 的目的是什么?

This note 说:

-ansi:告诉编译器实现 ANSI 语言选项。这会关闭与 ANSI 标准不兼容的 GCC 的某些“功能”。 -pedantic:与 -ansi 一起使用,这告诉编译器严格遵守 ANSI 标准,拒绝任何不符合标准的代码。

第一件事:

GCC/G++ 编译器的 -pedantic 和 -ansi 选项的目的是什么(我看不懂上面的描述)?

使用这两个选项的正确情况是什么?

我应该什么时候使用它们?

它们重要吗?


J
Jonathan Leffler

我在编码中一直使用它。

-ansi 标志等同于 -std=c89。如前所述,它关闭了 GCC 的一些扩展。添加 -pedantic 会关闭更多扩展并生成更多警告。例如,如果您的字符串文字长度超过 509 个字符,则 -pedantic 会发出警告,因为它超出了 C89 标准要求的最小限制。也就是说,每个 C89 编译器都必须接受长度为 509 的字符串;它们被允许接受更长的时间,但是如果你是迂腐的,使用更长的字符串是不可移植的,即使编译器被允许接受更长的字符串,并且在没有迂腐警告的情况下,GCC 也会接受它们。


@huahsin68:嗯,或多或少。 MSVC 是一个与大多数其他编译器相当不同的编译器,更适合其特定的生态系统,并且在它之外不可用。它以自己的方式做很多事情——这与标准不同。不过,如果您继续使用标准头文件等,那么 MSVC 和 GCC 非常相似。但是,使用 -std=c89 -pedantic 确实意味着您可以更轻松地在其他平台上的不同编译器之间移动。一旦您开始使用 <windows.h>,与其他系统的兼容性就会出现问题。
@slf:因为和其他所有供应商一样(尽管 GNU 不会以现金出售他们的编译器),他们希望您使用他们的专有功能?或者,更一般地说,因为他们认为这些扩展很有用,并认为它们应该默认启用。
对于它的价值和 JFTR,我基本上已经停止使用 -pedantic,但是当我重新启用它时,我的大部分代码仍然可以正常编译(一个没有明确使用 __int128 类型的程序, 迂腐不正确)。我认为当 GCC 对 -pedantic 过于嘈杂(我喜欢)时,存在一个中间阶段。我刚刚测试了大约 300 个源文件——一些库代码、一些命令、一些 SO 测试程序——而且只有一个预期的问题。目前在 Mac OS X 10.9.2 上使用 GCC 4.8.2。
@JonathanLeffler,是的,我正在查询实际编译器的名称是什么,这不起作用?甚至有一个这样的编译器吗?
请注意,gcc 早于标准,我怀疑作者希望标准包含一些从 C89 中排除的 gcc 功能。 -pedantic 标志基本上用于标记 gcc 的作者认为质量编译器应该支持的东西。 gcc 作者对标准的态度与其维护者今天的态度截然不同。
P
Peter Mortensen

如果可能的话,GCC 编译器总是试图编译你的程序。但是,在某些情况下,C 和 C++ 标准指定禁止某些扩展。遇到这些扩展时,符合标准的编译器(例如 GCC 或 g++)必须发出诊断。

例如,GCC 编译器的 -pedantic 选项会导致 GCC 在这种情况下发出警告。使用更严格的 -pedantic-errors 选项会将此类诊断警告转换为将导致编译在此类点失败的错误。只有那些需要由符合标准的编译器标记的非 ISO 结构才会生成警告或错误。


ISO C 和 C++ 标准仅“禁止扩展”,因为扩展不得改变任何符合标准的程序的行为。编译器不会被迫拒绝任何使用扩展的程序。
@MM:重要的是要注意,当一些编译器会接受一个有用的结构而其他人会拒绝它时,委员会的“妥协”是让符合要求的实现必须发出一个程序员可以忽略的诊断,从而避免委员会需要强制或禁止构造。
请注意,-pedantic-errors-Werror=pedantic 不同。他们执行不同的检查。
P
Peter Mortensen

<-ansi 是一个过时的开关,它要求编译器根据已有 30 年历史的过时的 C 标准修订版ISO/IEC 9899:1990 进行编译,这本质上是对ANSI标准X3.159-1989“编程语言C的更名。为什么过时了?因为C90由ISO发布之后,ISO一直负责C的标准化,任何< em>C90 的技术勘误已被 ISO 标准化,因此更适合使用 -std=c90

如果没有此开关,最新的 GCC C 编译器将符合 ISO/IEC 9899:2011 或最新的 2018 修订版中标准化的 C 语言。

不幸的是,有一些懒惰的编译器供应商认为坚持使用较旧的过时标准修订版是可以接受的,标准机构甚至没有标准化文档。

使用该开关有助于确保代码应该在这些过时的编译器中编译。

-pedantic 很有趣。在没有 -pedantic 的情况下,即使请求了特定的标准,GCC 仍将允许一些 C 标准中不可接受的扩展。例如考虑程序

struct test {
    int zero_size_array[0];
};

C11 draft n1570 paragraph 6.7.6.2p1 says

除了可选的类型限定符和关键字 static,[ 和 ] 可以分隔表达式或 *。如果它们分隔了一个表达式(它指定了一个数组的大小),则该表达式应为整数类型。如果表达式是常量表达式,则它的值应大于零。[...]

C标准要求数组长度大于零;并且这一段在约束中;该标准规定以下 5.1.1.3p1

如果预处理翻译单元或翻译单元包含违反任何语法规则或约束的行为,则符合要求的实现应产生至少一个诊断消息(以实现定义的方式标识),即使该行为也明确指定为未定义或实现-定义。在其他情况下不需要生成诊断消息。9)

但是,如果使用 gcc -c -std=c90 pedantic_test.c 编译程序,则不会产生警告。

-pedantic 使编译器实际上符合 C 标准;所以现在它将产生一条诊断消息,正如标准所要求的:

gcc -c -pedantic -std=c90 pedantic_test.c
pedantic_test.c:2:9: warning: ISO C forbids zero-size array ‘zero_size_array’ [-Wpedantic]
     int zero_size_array[0];
         ^~~~~~~~~~~~~~~

因此,为了获得最大的可移植性,仅指定标准版本是不够的,您还必须使用 -pedantic(或 -pedantic-errors)来确保 GCC 确实符合标准的规定。

问题的最后一部分是关于将 -ansiC++ 一起使用。 ANSI 从未对 C++ 语言进行标准化 - 仅从 ISO 中采用它,因此这与说“法国标准化的英语”一样有意义。然而 GCC 似乎仍然接受它用于 C++,这听起来很愚蠢。


请注意,已经对语言标准进行了进一步的修订。今天我通常使用 -std=c11 -Wall -Wextra -Wpedantic -Wconversion 进行编译。
我还要补充一点,您应该始终明确指定标准。例如 -std=c++20
P
Peter Mortensen

基本上,它将使您的代码更容易在也实现 ANSI 标准的其他编译器下编译,并且,如果您小心使用哪些库/API 调用,则在其他操作系统/平台下编译。

第一个关闭 GCC 的特定功能 (-ansi)。

第二个会抱怨任何不符合标准的东西(不仅是 GCC 的特定功能,还有你的构造。)(-pedantic)。


P
Peter Mortensen

如果您的代码需要可移植,那么您可以测试它是否可以在没有任何 GCC 扩展或其他非标准功能的情况下进行编译。如果您的代码使用 -pedantic -ansi 编译,那么理论上它应该可以使用任何其他 ANSI 标准编译器编译。


-pedantic 不会关闭所有扩展,它会留下一堆双下划线的东西。因此,更准确的说法是,如果您的代码使用 -pedantic -ansi 进行编译,并且看起来似乎可以在其他实现上编译,那么它就会编译。
你提到双下划线的东西,这听起来很有趣。你到底指的是什么?
一个例子是 gcc 的“__asm__()”内联汇编代码,它适用于 gcc,但双下划线可能不适用于 Windows 编译器,即使该编译器确实符合标准。
D
Damien_The_Unbeliever

如果您正在编写您设想将在各种平台上使用许多不同编译器编译的代码,那么您自己使用这些标志将有助于确保您不会生成仅在 GCC 下编译的代码。


在某些版本的 GCC 下!
C
Community

其他人已经充分回答了。我只想添加一些频繁扩展的示例:

main 函数返回 void。这不是由标准定义的,这意味着它只能在某些编译器(包括 GCC)上工作,而不能在其他编译器上工作。顺便说一下,int main()int main(int, char**) 是标准定义的两个签名。

另一个流行的扩展是能够在其他函数中声明和定义函数:

void f()
{
    void g()
    {
       // ...
    }

    // ...
    g();
    // ...
}

这是非标准的。如果您想要这种行为,请查看 C++11 lambdas


P
Peter Mortensen

Pedantic 使得 GCC 编译器拒绝所有 GNU C 扩展,而不仅仅是那些使其与 ANSI 兼容的扩展。


这太有趣了。您提到了 GNU C 扩展,这些扩展可能也可能不在 ANSI 标准中。我能有更多关于这个的信息吗?我在哪里可以获得这些适当的资源?