我是否需要GCC和C11的-dantic旗帜?

我目前正在使用GCC-5.3在我的机器上运行Linux Mint ,因为C11是默认包含的。

我开始为自己学习C只是为了好玩,当时GCC版本是4.8如果我没记错的话。

如果在下面的程序中使用带有-pedantic标志的GCC-4.8 ,任何方式:

 #include  #include  int main(void){ char *arr = "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"; size_t length = strlen(arr); printf("Length of Arr = %zu\n",length); } 

在编译时,会收到以下警告:

 program.c: In function 'main': program.c:5:5: warning: string length '510' is greater than the length '509' ISO C90 compilers are required to support [-Woverlength-strings] char *arr = "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"; ^ program.c:7:5: warning: ISO C90 does not support the 'z' gnu_printf length modifier [-Wformat=] printf("Length of Arr = %zu\n",length); ^ program.c:8:1: warning: control reaches end of non-void function [-Wreturn-type] } ^ 

如果我们看到这部分警告:

 warning: string length '510' is greater than the length '509' ISO C90 compilers are required to support [-Woverlength-strings] 

在某种程度上清楚 – -pedantic标志是一个问题在这里所以我决定不使用它并避免它像避免-ansi因为新的(最后)标准C11

现在如果我用GCC-5.3编译相同的程序:

 gcc-5 -Wall -pedantic program.c -o program 

该程序编译良好,没有警告。

现在基于以下问题在C和C ++中返回void类型,如果我尝试编译以下程序:

 #include  #include  void f(void); void f2(void); int main(void){ f(); } void f(void){ } void f2(void){ return f(); } 

具有以下内容:

 gcc-5 -Wall -pedantic program.c -o program 

我明白了:

 program.c: In function 'f2': program.c:16:16: warning: ISO C forbids 'return' with expression, in function returning void [-Wpedantic] return f(); ^ 

但是没有“迂腐”旗帜就可以编好。 这对我来说很困惑。

这告诉我,不知怎的,我确实需要-pedantic旗帜,但我并不痛。

所以,我的问题是, 我们是否需要使用 C11 来使用 -pedantic

如果您需要它,您需要它。 如果你不这样做,你就不会。

gcc的-pedantic选项告诉它严格执行您要求的C标准规则。 这会导致其他警告消息(如果使用-pedantic-errors致命-pedantic-errors )。

问题是,您是否希望编译器警告您违反C标准要求的代码?

如果您希望代码尽可能便携,请使用-pedantic并密切关注它告诉您的任何内容。 如果您希望代码依赖于非标准function,请不要使用-pedantic – 但是您可能会遇到代码可能无法使用其他编译器和/或不同目标系统进行编译的风险。

您遇到的具体信息是针对C90和C11之间发生变化的事情。 C11要求编译器在字符串文字中支持至少4095个字符; C90只需要509.(实际上,对于gcc,实际限制不是固定的,而是在编译时由可用内存强加。标准中描述限制的方式并不那么简单,但我不会进入那个。)尽管如此,你很少需要一个字符串文字。

C99添加了%zu格式,用于打印size_t类型的值。 如果您希望您的代码可以移植到C99之前的实现,那么您将需要避免使用它; 例如,您可以使用printf("%lu\n", (unsigned long)sizeof foo) 。 实际上,大多数当前的实现都支持%zu

带有表达式的return语句,甚至是void类型的表达式,在使用void返回类型定义的函数中是不允许的。 这是你应该要的警告(恕我直言)。

结论:如果要严格执行C标准的规则,请使用-pedantic 。 如果您不想这样做,请不要使用-pedantic 。 (但是考虑使用-pedantic编译代码,至少偶尔会清除它检测到的任何真正的错误,除了你可能不关心的警告。)

最初的C C89 / C90标准只要求编译器允许字符串文字长达509个字节。 使用长度超过509字节的字符串编译为C90标准的代码不是最大可移植的; 符合标准的编译器可以拒绝代码。 它在实践中不太可能成为问题,但理论上可能会发生。

限制在C99中提高到4095字节(并且在C11中保持不变)。 因此,您必须使用更长的字符串才能使用C99或C11来限制极限。

GCC 4.x编译器默认使用C90标准。 GCC 5.x编译器默认使用C11标准。 因此,在GCC 4.x下使用-pedantic进行编译时,不能最大程度地移植到C90的代码将生成警告,但不会生成与GCC 5.x相同的警告,除非该构造也不能移植到所有C11编译器 – 除非它也违反了C11编译时限制之一。

-pedantic旗帜有其用途。 例如,昨天,有人遇到问题,因为他们正在使用:

 void *p = malloc(sizeof(*p)); 

根据标准,这是错误的代码,但GCC(5.3.0专门测试,但其他5.x和4.x版本的行为相同)允许它,将sizeof(*p)解释为1 。 这对其他编译器来说是不可移植的。 使用-pedantic报告问题; 不使用-pedantic不。

从正式的角度来看,如果你打算用标准C编写你的代码,你肯定需要-pedantic标志(而且, -pedantic-errors可能是更好的主意)。 然而, -pedantic的最初实现遭受了一个相当可疑的设计决策:它包括与实现限制相关的警告(这是可以的),并且最重要的是它也在-pedantic-errors模式-pedantic-errors它们变成了错误(其中,我的意见,是不可接受的)。

关于实现限制的警告可能是有用的,但仍然可以保持它们独立可控,保持-pedantic为直接的约束违规保留。

事实上你不再看到有关实施限制的警告 – -pedantic可能意味着GCC 5最终决定照顾这个问题。 如果是这样,那将是一个值得欢迎的改变(但更可能是改变的限制)。

-pedantic只是一个标志,可以打开一大堆警告和错误,如果你愿意,你可以使用它,但听起来你真的没有使用c11,否则它不会给你那个特别的警告……

尝试:

 gcc -std=c11 -Wall -pedantic program.c -o program 

这将使pre gcc-5版本使用C11 std作为默认值而不是gnu89

The default mode for C is now -std=gnu11 instead of -std=gnu89

来自gcc.gnu.org/gcc-5/changes.html

并且更详细一点:c11和gnu11之间的区别是微妙的,我没有仔细研究c11,但是在c99 / gnu99中,关系是gnu99是c11的超集并允许一些编译器扩展到语言…我非常怀疑这与c11 / gnu11的关系是一样的

错误消息末尾的[-Wpedantic]表示警告是由-pedantic编译器选项生成的。 换句话说, -pedantic已经启用。

你不需要-pedantic标志。 几乎没有人需要-pedantic旗帜。

Pedantry – 过度关注细节和规则。

实际上,根据定义,可以忽略 – 警告。 在编写跨平台代码时,该标志可能很有用,但就是这样。