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


136

此说明说:

-ansi:告诉编译器实现ANSI语言选项。这将关闭GCC的某些“功能”,这些功能与ANSI标准不兼容。

-pedantic:与结合使用-ansi,可以告诉编译器严格遵守ANSI标准,拒绝任何不符合要求的代码。

首先要注意的是:

  • GCC / G ++编译器的-pedantic-ansi选项的目的是什么(我听不懂上面的描述)?
  • 谁能告诉我使用这两个选项的正确情况?
  • 我什么时候应该使用它们?
  • 他们重要吗?

Answers:


84

如果有可能,GCC编译器总是尝试编译您的程序。但是,在某些情况下,C和C ++标准指定禁止某些扩展。遇到这些扩展时,合格的编译器(例如gcc或g ++)必须发出诊断信息。例如,在这种情况下,gcc编译器的-pedantic选项使gcc发出警告。使用严格的 -pedantic-errors选项会将此类诊断警告转换为错误,这些错误将导致编译在此类情况下失败。只有那些由合格编译器标记的非ISO构造才会生成警告或错误。


3
ISO C和C ++标准仅“禁止扩展”,因为扩展不得更改任何符合程序的行为。不会强制编译器拒绝任何使用扩展名的程序。
MM

@MM:必须指出的是,当一些编译器会接受有用的构造而其他人会拒绝它时,委员会的“妥协”是使符合标准的实现必须发出诊断,然后程序员可以忽略该诊断,从而避免委员会需要强制或禁止构造。
supercat

105

我在编码中一直使用它。

-ansi标志等效于-std=c89。如前所述,它关闭了GCC的某些扩展。添加-pedantic将关闭更多扩展名并生成更多警告。例如,如果您的字符串文字长于509个字符,则会-pedantic发出警告,因为它超出了C89标准要求的最小限制。也就是说,每个C89编译器必须接受长度为509的字符串。允许它们接受更长的字符串,但是如果您是书呆子,则即使允许编译器接受更长的字符串,也不能使用更长的字符串,并且在没有书呆子警告的情况下,GCC也将接受它们。


-ansi关闭GCC的某些扩展,而-pedantic关闭更多的扩展。看来-ansi是一级规则,然后-pedantic是更严格的规则。这是否意味着删除这两个选项,我可以使我的代码与Microsoft的其他编译器更兼容?
huahsin68

4
@ huahsin68:或多或少。MSVC是与大多数其他软件完全不同的编译器,更适合其特定的生态系统,并且在外部无法使用。它以自己的方式做很多事情-与标准不同。但是,如果您使用标准标头等,则MSVC和GCC相当相似。但是,使用-std=c89 -pedantic确实意味着您可以在其他平台上的不同编译器之间更轻松地移动。一旦开始使用<windows.h>,与其他系统的兼容性就会成问题。
乔纳森·勒夫勒

2
@slf:因为像其他所有供应商一样(尽管GNU不会以现金出售其编译器),他们希望您使用其专有功能吗?或者,更一般而言,因为它们认为扩展有用,并且认为默认情况下应启用它们。
乔纳森·莱夫勒

1
无论是什么价值,以及JFTR,我都几乎停止使用-pedantic,但是当我重新启用它时,我的大部分代码仍然可以编译(一个程序没有明确使用__int128类型,这理论上是错误的)。我认为有一个中间阶段,即GC​​C太嘈杂(按我的喜好)-pedantic。我刚刚测试了大约300个源文件-一些库代码,一些命令,一些SO测试程序-只是一个预期的问题。当前在Mac OS X 10.9.2上使用GCC 4.8.2。
乔纳森·勒夫勒

1
@JonathanLeffler,是的,我正在查询实际无法使用的实际编译器名称是什么?甚至有一个这样的编译器吗?
和平者

23

-ansi是请求编译器根据30岁的编译一个过时的开关的C标准过时修订ISO / IEC 9899:1990,这基本上是ANSI标准的一个更名X3.159-1989“C语言编程。为什么过时呢?因为ISO发行了C90之后,ISO才负责C的标准化工作,而ISO发行了有关C90的任何技术勘误,因此更容易使用-std=c90

如果不进行此切换,则最新的GCC C编译器将符合ISO / IEC 9899:2011或最新的2018版本中标准化的C语言。

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

使用开关有助于确保代码可以在这些过时的编译器中进行编译。


-pedantic是一个有趣的。如果没有-pedantic,即使要求使用特定标准,GCC仍将允许某些C标准不接受的扩展。考虑例如程序

struct test {
    int zero_size_array[0];
};

C11草案n1570款6.7.6.2p1说

除了可选的类型限定符和关键字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 ++,听起来很愚蠢。


4
请注意,语言标准已有进一步的修订。今天,我通常使用进行编译-std=c11 -Wall -Wextra -Wpedantic -Wconversion
戴维斯洛

14

基本上,这将使您的代码更容易在也实现ANSI标准的其他编译器下进行编译,并且,如果您在使用哪种库/ api调用时非常谨慎,则可以在其他操作系统/平台下进行编译。

第一个,关闭GCC的特定功能。(-ansi)第二个,将抱怨根本不符合标准的任何东西(不仅是GCC的特定功能,还包括您的构造。)(-pedantic)。


6

如果您的代码需要具有可移植性,那么您可以测试其编译时没有任何gcc扩展或其他非标准功能。如果您的代码可以编译,-pedantic -ansi那么理论上它应该可以与任何其他ANSI标准编译器一起编译。


4
-pedantic不会关闭所有扩展名,而是留下了很多双下划线的内容。因此,如果您的代码使用进行编译-pedantic -ansi,并且看起来好像也可以在其他实现上进行编译,那么它会进行编译可能更准确。
史蒂夫·杰索普

3
您提到了双下划线的内容,这听起来很有趣。您指的是什么?
huahsin68

一个例子是gcc的“ __asm __()”内联汇编代码,它对gcc很好,但是即使Windows编译器确实符合标准,双下划线也可能无法正常工作。


1

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

main函数返回void。这不是标准定义的,这意味着它仅适用于某些编译器(包括GCC),而不适用于其他编译器。顺便说一句,int main()int main(int, char**)是标准确实定义的两个签名。

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

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

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

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


0

Pedantic做到这一点,以便gcc编译器不仅拒绝所有ANSI兼容的扩展,还拒绝所有GNU C扩展。


1
这是如此有趣。您提到了GNU C扩展,这些扩展可能会也可能不在ANSI标准中。我可以对此有更多信息吗?我在哪里可以得到那些合适的资源?
huahsin68
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.