我需要 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 最终决定处理此事。如果是这样,那将是一个可喜的变化(但更有可能是限制发生了变化)。