【问题标题】:Do I need -pedantic flag from GCC with C11?我需要来自 GCC 的带有 C11 的 -pedantic 标志吗?
【发布时间】:2016-06-29 21:41:41
【问题描述】:

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

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

如果有人在以下程序中使用GCC-4.8-pedantic 标志,那么无论如何:

#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

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

如果我尝试编译以下程序,现在基于以下问题Return void type in C and C++

#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 anymoreC11

【问题讨论】:

    标签: c gcc c11


    【解决方案1】:

    最初的 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 不会。

    【讨论】:

      【解决方案2】:

      -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 的关系相同

      【讨论】:

      • gcc-5 -std=c11gcc-5 相同,因为默认使用 C11
      • @Michi:GCC 5 的默认值为-std=gnu11,而不是-std=c11
      • @KeithThompson 据我了解-std=gnu11 表示C11GNU extensions。那么请解释C11 是如何不默认的? ...或者标准中缺少一些部分?因为这让我相信我需要明确使用 -std=C11GCC-5 来禁用这些扩展?
      • @Michi: -std=c11 指定 C11。 -std=gnu11 是默认值,它指定了带有 GNU 扩展的 C11。这在gcc manual 中有解释。
      【解决方案3】:

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

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

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

      如果您希望您的代码尽可能可移植,请使用-pedantic 并密切注意它告诉您的任何内容。如果您希望您的代码依赖于非标准功能,请不要使用 -pedantic - 但您的代码可能无法使用不同的编译器和/或不同的目标系统进行编译。

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

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

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

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

      【讨论】:

      • 我怀疑%lu 对于size_t 来说是便携
      • 完全正确,我忘记了演员表。 (编辑:我现在添加了它。)它仍然不是 100% 可移植的(如果 sizeofunsigned long并且 大小超过 ULONG_MAX,它将打印不正确的值,这至少是 2**32-1),但至少可以移植回 C90。
      【解决方案4】:

      从形式上看,如果您打算用标准 C 编写代码,您肯定需要-pedantic 标志(此外,-pedantic-errors 可能是更好的主意)。然而,-pedantic 的原始实现遇到了一个相当有问题的设计决策:它包括与实现限制相关的警告(这没问题),除此之外,它还在-pedantic-errors 模式下将它们变成了错误(在我的意见,是不可接受的)。

      关于实施限制的警告可能有用,但保持它们独立可控可能是个好主意,将-pedantic 保留用于直接违反约束。

      您不再看到有关-pedantic 的实现限制的警告这一事实可能意味着 GCC 5 最终决定处理此问题。如果是这样,那将是一个可喜的变化(但更可能是限制发生了变化)。

      【讨论】:

        【解决方案5】:

        您不需要-pedantic 标志。几乎没有人需要-pedantic 标志。

        迂腐 - 过分关注小细节和规则。

        -pedantic 警告可以忽略,实际上根据定义。该标志在编写跨平台代码时可能很有用,但仅此而已。

        【讨论】:

        • 我不同意。我建议阅读 gcc 的 -pedantic 选项的文档。没有它,gcc 不完全符合任何版本的 C 标准。
        • 恰恰相反。 -pedantic 是必须的,应该默认启用,特别是如果用户通过-std=... 标志明确选择特定的语言标准。
        • 英语词典对“管道”一词的定义是否会影响您使用gcc -pipe 的决定?选择pedantic 一词反映了(一些?)gcc 维护者的意见。不是每个人都同意这种观点。
        • 仅仅因为 GCC 的编译器选项名称选择不当,并不意味着它是外围利益。在 GCC 中 -pedantic-errors 表示:“根据 C 标准编译我的 C 代码”。因此,如果您想要符合标准的代码,则必须使用它。它应该与相关的 -std 选项一起使用,例如 `gcc -pedantic-errors -std=c11' 表示“根据 C 标准编译我的 C 代码,C11 版本”。将此与没有标志进行比较,这意味着“让 gnu 编译我的非标准代码,当我调用各种形式的定义不明确的行为时请不要警告我”。
        • -pedantic 的反义词是 gnu。根据牛津词典,gnu 的意思是:“一种大型深色羚羊,头长,有胡须和鬃毛,背部倾斜。也称为角马。”
        【解决方案6】:

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

        【讨论】:

        • 谢谢,但这不能回答我的问题。我在我的问题But compiles fine without the ´-pendantic 标志处编辑的任何方式。这让我很困惑。`请检查一下。
        • 如果我用 gcc-5 -Q -v program.c 编译`我看不到 -pendantic is enabled
        • @Michi 如果您想使用-pedantic 选项进行编译,请将该选项传递给编译器。
        猜你喜欢
        • 1970-01-01
        • 2015-02-12
        • 2020-02-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-14
        • 2023-03-14
        • 2016-09-11
        相关资源
        最近更新 更多