Answers:
如果有可能,GCC编译器总是尝试编译您的程序。但是,在某些情况下,C和C ++标准指定禁止某些扩展。遇到这些扩展时,合格的编译器(例如gcc或g ++)必须发出诊断信息。例如,在这种情况下,gcc编译器的-pedantic选项使gcc发出警告。使用严格的
-pedantic-errors
选项会将此类诊断警告转换为错误,这些错误将导致编译在此类情况下失败。只有那些由合格编译器标记的非ISO构造才会生成警告或错误。
我在编码中一直使用它。
该-ansi
标志等效于-std=c89
。如前所述,它关闭了GCC的某些扩展。添加-pedantic
将关闭更多扩展名并生成更多警告。例如,如果您的字符串文字长于509个字符,则会-pedantic
发出警告,因为它超出了C89标准要求的最小限制。也就是说,每个C89编译器必须接受长度为509的字符串。允许它们接受更长的字符串,但是如果您是书呆子,则即使允许编译器接受更长的字符串,也不能使用更长的字符串,并且在没有书呆子警告的情况下,GCC也将接受它们。
-std=c89 -pedantic
确实意味着您可以在其他平台上的不同编译器之间更轻松地移动。一旦开始使用<windows.h>
,与其他系统的兼容性就会成问题。
-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];
};
除了可选的类型限定符和关键字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确实符合标准的规定。
这个问题的最后一部分是有关使用-ansi
与C ++。ANSI从未对C ++语言进行标准化,仅从ISO采纳它,因此这与说“法国标准化的英语”一样有意义。但是,GCC似乎仍然接受C ++,听起来很愚蠢。
-std=c11 -Wall -Wextra -Wpedantic -Wconversion
。
其他人已经回答了。我只想添加一些频繁扩展的示例:
该main
函数返回void
。这不是标准定义的,这意味着它仅适用于某些编译器(包括GCC),而不适用于其他编译器。顺便说一句,int main()
和int main(int, char**)
是标准确实定义的两个签名。
另一个流行的扩展是能够在其他函数中声明和定义函数:
void f()
{
void g()
{
// ...
}
// ...
g();
// ...
}
这是非标准的。如果您想要这种行为,请查看C ++ 11 lambdas