What is the purpose of using -pedantic in the GCC/G++ compiler?

This note says:

-ansi: tells the compiler to implement the ANSI language option. This turns off certain "features" of GCC which are incompatible with the ANSI standard.

-pedantic: used in conjunction with -ansi, this tells the compiler to be adhere strictly to the ANSI standard, rejecting any code which is not compliant.

First things first:

  • What is the purpose of the -pedantic and -ansi options of the GCC/G++ compiler (I couldn't understand the above description)?
  • What are the right circumstances for using these two options?
  • When should I use them?
  • Are they important?
153760 次浏览

如果您的代码需要是 便携式的,那么您可以测试它是否在没有任何 GCC 扩展或其他非标准特性的情况下编译。如果你的代码用 -pedantic -ansi编译,那么理论上它应该用任何其他 ANSI 标准编译器编译 OK。

如果你所编写的代码是在各种各样的平台上编译的,有许多不同的编译器,那么自己使用这些标志将有助于确保你不会产生只在 GCC 下编译的代码。

我在编程的时候一直在用。

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

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

第一个关闭了 GCC (< a href = “ https://gcc.gnu.org/onlinedocs/gcc/C-Direcect-Options.html # index-ANSI-support”rel = “ nofollow noReferrer”>-ansi )的 具体点特性。

第二种方法会抱怨 什么都行根本不符合标准(不仅是 GCC 的特定特性,还有您的构造)(一个 href = “ https://gcc.gnu.org/onlinedocs/gcc/Police-Options.html # index-pedantic-1”rel = “ nofollow noReferrer”>-pedantic ).

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

如果可能的话,GCC 编译器总是尝试编译您的程序 情况下,C 和 C + + 标准规定禁止某些扩展 当遇到这些扩展时,如 GCC 或 g + + 必须发出诊断。

例如,在这种情况下,GCC 编译器的 一个 href = “ https://gcc.gnu.org/onlinedocs/gcc/Police-Options.html # index-pedantic-1”rel = “ noReferrer”>-pedantic 选项会导致 GCC 发出警告。使用更严格的 一个 href = “ https://gcc.gnu.org/onlinedocs/gcc/Police-Options.html # index-pedantic-error-1”rel = “ noReferrer”>-pedantic-error 选项将这种诊断警告转换为错误,这将导致在这些点上编译失败。只有那些需要由符合要求的编译器标记的非 ISO 构造才会生成警告或错误。

其他人已经做出了充分的回答,我只想补充一些频繁扩展的例子:

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

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

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


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

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

< -ansi是一个过时的开关,它要求编译器根据有30年历史的 过时的 C 标准修订本ISO/IEC 9899:1990进行编译,ISO/IEC 9899:1990实质上是 ANSI 标准 X3.159-1989“程序设计语言 C”的重新命名。为什么过时?因为在 C90被 ISO 公布之后,ISO 就负责 C 的标准化,任何 技术纠正到 C90都被 ISO 标准化了。因此它更倾向于使用 -std=c90

如果没有这个转换,最近的 GCC C 编译器将遵循 ISO/IEC 9899:2011中标准化的 C 语言,或者2018年的最新版本。

不幸的是,有些懒惰的编译器供应商认为,坚持使用过时的标准版本是可以接受的,因为标准化文档甚至不能从标准主体中获得。

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


-pedantic是一款有趣的产品。在没有 -pedantic的情况下,即使请求了特定的标准,GCC 仍然允许一些在 C 标准中不可接受的扩展。以程序为例

struct test {
int zero_size_array[0];
};

返回文章页面 C11草案 n1570第6.7.6.2段 p1说:

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

C 标准要求数组长度大于零; 这一段在 约束中; 标准说明如下 5.1.1.3 p1:

如果预处理翻译单元或翻译单元违反了任何语法规则或约束,即使该行为也被明确指定为未定义或实现定义,符合规范的实现应该产生至少一条诊断消息(以实现定义的方式标识)。在其他情况下不需要产生诊断信息。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 实际上符合标准的字面意思。


问题的最后一部分是关于在 C + + 中使用 -ansi。ANSI 从来没有标准化过 C + + 语言——只是从 ISO 采用了它,所以这就像说“法国标准化的英语”一样有意义。然而,GCC 似乎仍然接受 C + + 使用它,尽管这听起来很愚蠢。