我需要 GCC 的 -pedantic 标志和 C11 吗?
Do I need -pedantic flag from GCC with C11?
我目前 运行 Linux Mint
在我的机器上使用 GCC-5.3
因为 C11
是默认包含的。
我开始为自己学习 C
只是为了好玩,当时 GCC
版本是 4.8
如果我没记错的话。
如果在以下程序中使用带有 -pedantic
标志的 GCC-4.8
的任何方式:
#include <stdio.h>
#include <string.h>
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
程序编译正常,没有警告。
现在根据下面的问题如果我尝试编译下面的程序:
#include <stdio.h>
#include <string.h>
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` 标志也可以正常编译。这让我很困惑。
这表明我确实需要 -pedantic
标志,但我并不痛。
所以,我的问题是,我们是否需要再使用 -pedantic
和 C11
?
错误消息末尾的 [-Wpedantic]
表示警告是由 -pedantic
编译器选项生成的。换句话说 -pedantic
已经启用。
您不需要 -pedantic
标志。几乎没有人需要 -pedantic
标志。
迂腐 - 过分关注细节和规则。
-pedantic
警告可以忽略,实际上根据定义。该标志在编写跨平台代码时可能很有用,仅此而已。
如果你需要它,你就需要它。如果你不这样做,你就不会。
gcc 的 -pedantic
选项告诉它严格执行您所请求的 C 标准的规则。这会导致出现额外的警告消息(如果您使用 -pedantic-errors
,则会出现致命错误)。
问题是,您希望编译器警告您有关违反 C 标准要求的代码吗?
如果您希望您的代码尽可能可移植,请使用 -pedantic
并密切注意它告诉您的任何内容。如果您希望您的代码依赖于非标准功能,请不要使用 -pedantic
—— 但是您 运行 可能会面临您的代码可能无法使用其他编译器 and/or 进行编译的风险不同的目标系统。
您 运行 收到的特定消息是关于 C90 和 C11 之间发生变化的内容。 C11 要求编译器在字符串文字中支持至少 4095 个字符; C90 只需要 509。(实际上,对于 gcc,实际限制不是固定的,而是在编译时由可用内存强加的。标准中描述限制的方式并不那么简单,但我不会深入那个。)不过,你很少需要那么长的字符串文字。
C99 添加了 %zu
格式来打印 size_t
类型的值。如果您希望您的代码可移植到 C99 之前的实现,则需要避免使用它;例如,您可以使用 printf("%lu\n", (unsigned long)sizeof foo)
。实际上,大多数当前实现都支持 %zu
.
带有表达式的 return
语句,即使是 void
类型的表达式,在使用 void
return 类型定义的函数中也是不允许的。这是你应该想要的警告(恕我直言)。
底线:如果您想严格执行 C 标准的规则,请使用 -pedantic
。如果您不想这样做,请不要使用 -pedantic
。 (但考虑至少偶尔使用 -pedantic
编译您的代码,以清除它检测到的任何实际错误,以及您可能不关心的警告。)
最初的 C C89/C90 标准只要求编译器允许最大 509 字节长的字符串文字。使用长度超过 509 字节的字符串编译为 C90 标准的代码不是最大可移植的;符合标准的编译器可能会拒绝该代码。这在实践中不太可能成为问题,但理论上可能会发生。
C99 中的限制提高到 4095 字节(在 C11 中保持不变)。因此,您必须有更长的字符串才能 运行 违反 C99 或 C11 的限制。
GCC 4.x 编译器默认使用 C90 标准。 GCC 5.x 编译器默认使用 C11 标准。因此,不能最大程度地移植到 C90 的代码在 GCC 4.x 下使用 -pedantic
编译时将生成警告,但不会生成与 GCC 5.x 相同的警告,除非构造也不是可移植到所有 C11 编译器——除非它也违反了 C11 编译时限制之一。
-pedantic
标志有其用途。例如,昨天,有人 运行 遇到了问题,因为他们正在使用:
void *p = malloc(sizeof(*p));
根据标准,这是格式错误的代码,但 GCC(5.3.0 专门测试,但其他 5.x 和 4.x 版本表现相同)允许它,解释 sizeof(*p)
作为 1
。这不能移植到其他编译器。使用 -pedantic
报告问题;不使用 -pedantic
不会。
-pedantic 只是一个标志,可以打开一大堆警告和错误,如果你愿意,你可以使用它,但听起来你真的没有使用 c11,否则它不会给你那个特别警告...
尝试:
gcc -std=c11 -Wall -pedantic program.c -o program
这将使 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
的关系相同
从正式的角度来看,如果您计划用标准 C 编写代码,您肯定需要 -pedantic
标志(此外,-pedantic-errors
可能更好)。然而,-pedantic
的原始实现遭遇了一个相当有问题的设计决策:它包含与实现限制相关的警告(这没关系),除此之外,它还在 -pedantic-errors
模式下将它们变成了错误(在我看来,这是不可接受的)。
关于实施限制的警告可能有用,但让它们保持独立可控仍然是个好主意,保持 -pedantic
保留用于直接违反约束。
您不再看到有关 -pedantic
的实施限制警告这一事实可能意味着 GCC 5 最终决定处理此事。如果是这样,那将是一个可喜的变化(但更有可能是限制发生了变化)。
我目前 运行 Linux Mint
在我的机器上使用 GCC-5.3
因为 C11
是默认包含的。
我开始为自己学习 C
只是为了好玩,当时 GCC
版本是 4.8
如果我没记错的话。
如果在以下程序中使用带有 -pedantic
标志的 GCC-4.8
的任何方式:
#include <stdio.h>
#include <string.h>
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
程序编译正常,没有警告。
现在根据下面的问题
#include <stdio.h>
#include <string.h>
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` 标志也可以正常编译。这让我很困惑。
这表明我确实需要 -pedantic
标志,但我并不痛。
所以,我的问题是,我们是否需要再使用 -pedantic
和 C11
?
错误消息末尾的 [-Wpedantic]
表示警告是由 -pedantic
编译器选项生成的。换句话说 -pedantic
已经启用。
您不需要 -pedantic
标志。几乎没有人需要 -pedantic
标志。
迂腐 - 过分关注细节和规则。
-pedantic
警告可以忽略,实际上根据定义。该标志在编写跨平台代码时可能很有用,仅此而已。
如果你需要它,你就需要它。如果你不这样做,你就不会。
gcc 的 -pedantic
选项告诉它严格执行您所请求的 C 标准的规则。这会导致出现额外的警告消息(如果您使用 -pedantic-errors
,则会出现致命错误)。
问题是,您希望编译器警告您有关违反 C 标准要求的代码吗?
如果您希望您的代码尽可能可移植,请使用 -pedantic
并密切注意它告诉您的任何内容。如果您希望您的代码依赖于非标准功能,请不要使用 -pedantic
—— 但是您 运行 可能会面临您的代码可能无法使用其他编译器 and/or 进行编译的风险不同的目标系统。
您 运行 收到的特定消息是关于 C90 和 C11 之间发生变化的内容。 C11 要求编译器在字符串文字中支持至少 4095 个字符; C90 只需要 509。(实际上,对于 gcc,实际限制不是固定的,而是在编译时由可用内存强加的。标准中描述限制的方式并不那么简单,但我不会深入那个。)不过,你很少需要那么长的字符串文字。
C99 添加了 %zu
格式来打印 size_t
类型的值。如果您希望您的代码可移植到 C99 之前的实现,则需要避免使用它;例如,您可以使用 printf("%lu\n", (unsigned long)sizeof foo)
。实际上,大多数当前实现都支持 %zu
.
带有表达式的 return
语句,即使是 void
类型的表达式,在使用 void
return 类型定义的函数中也是不允许的。这是你应该想要的警告(恕我直言)。
底线:如果您想严格执行 C 标准的规则,请使用 -pedantic
。如果您不想这样做,请不要使用 -pedantic
。 (但考虑至少偶尔使用 -pedantic
编译您的代码,以清除它检测到的任何实际错误,以及您可能不关心的警告。)
最初的 C C89/C90 标准只要求编译器允许最大 509 字节长的字符串文字。使用长度超过 509 字节的字符串编译为 C90 标准的代码不是最大可移植的;符合标准的编译器可能会拒绝该代码。这在实践中不太可能成为问题,但理论上可能会发生。
C99 中的限制提高到 4095 字节(在 C11 中保持不变)。因此,您必须有更长的字符串才能 运行 违反 C99 或 C11 的限制。
GCC 4.x 编译器默认使用 C90 标准。 GCC 5.x 编译器默认使用 C11 标准。因此,不能最大程度地移植到 C90 的代码在 GCC 4.x 下使用 -pedantic
编译时将生成警告,但不会生成与 GCC 5.x 相同的警告,除非构造也不是可移植到所有 C11 编译器——除非它也违反了 C11 编译时限制之一。
-pedantic
标志有其用途。例如,昨天,有人 运行 遇到了问题,因为他们正在使用:
void *p = malloc(sizeof(*p));
根据标准,这是格式错误的代码,但 GCC(5.3.0 专门测试,但其他 5.x 和 4.x 版本表现相同)允许它,解释 sizeof(*p)
作为 1
。这不能移植到其他编译器。使用 -pedantic
报告问题;不使用 -pedantic
不会。
-pedantic 只是一个标志,可以打开一大堆警告和错误,如果你愿意,你可以使用它,但听起来你真的没有使用 c11,否则它不会给你那个特别警告...
尝试:
gcc -std=c11 -Wall -pedantic program.c -o program
这将使 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
的关系相同从正式的角度来看,如果您计划用标准 C 编写代码,您肯定需要 -pedantic
标志(此外,-pedantic-errors
可能更好)。然而,-pedantic
的原始实现遭遇了一个相当有问题的设计决策:它包含与实现限制相关的警告(这没关系),除此之外,它还在 -pedantic-errors
模式下将它们变成了错误(在我看来,这是不可接受的)。
关于实施限制的警告可能有用,但让它们保持独立可控仍然是个好主意,保持 -pedantic
保留用于直接违反约束。
您不再看到有关 -pedantic
的实施限制警告这一事实可能意味着 GCC 5 最终决定处理此事。如果是这样,那将是一个可喜的变化(但更有可能是限制发生了变化)。