我是否需要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 – 过度关注细节和规则。
实际上,根据定义,可以忽略 – 警告。 在编写跨平台代码时,该标志可能很有用,但就是这样。