代码之家  ›  专栏  ›  技术社区  ›  ivo Welch

为什么GCC接受空指针算法不被认为是一个bug?[副本]

  •  0
  • ivo Welch  · 技术社区  · 10 年前

    关于C语言中如何禁止空指针运算,至少有三篇不同的帖子;gcc 4.8.2允许,假设一个空是字节大小;以及如何打开额外的迂腐警告来触发错误。下面是一个示例:

    #include <stdio.h>
    
    /* compile gcc -Wall -o try try.c */
    
    int main() {
      char *str="string";
      void *vp= (void *) str;
    
      ++vp; /* arithmetic on void point.  huh? */
    
      printf("%s\n", (char*)vp);
      return 0;
    }
    

    我的问题是思考C编译器在出现无效代码时应该做什么。当编译器不对无效代码发出编译错误时,是否不认为它是错误?

    对于编译器来说,这似乎是一种奇怪的行为,不管怎样,即使gcc没有发出编译错误,它至少会发出带有默认编译器标志的“不推荐”警告。而且,即使有 -Wall ,它甚至没有发出警告。嗯?这让我很惊讶,因为gcc在其他方面似乎很成熟,而C并不完全是一种新颖或复杂的语言。

    3 回复  |  直到 7 年前
        1
  •  12
  •   Keith Thompson    10 年前

    C标准尝试在 void* 约束违反 ,这意味着任何符合要求的C编译器必须为包含此类尝试的任何程序发出至少一条诊断消息。警告可能是非致命错误;在这种情况下,编译器可以继续生成其行为由实现定义的代码。

    默认情况下,gcc不会警告 无效* 这意味着默认情况下, 不是兼容的C编译器 .

    有人可能会说这是一个bug,但在默认模式下,gcc不是标准C的编译器,而是GNUC的编译器

    精心选择的命令行选项可以迫使gcc至少尝试一致。例如:

    gcc -std=cXX -pedantic
    

    哪里 XX 是其中之一 90 , 99 11 ,将导致gcc警告 无效* .更换 -pedantic 具有 -pedantic-errors 导致它将这种算法视为致命错误。

        2
  •  2
  •   Yu Hao    10 年前

    当然 无效的 标准C代码在特定编译器中可能是合法的,它被称为 编译器扩展 .

    这是真的,从 https://gcc.gnu.org/onlinedocs/gcc/Pointer-Arith.html

    在GNUC中,在指向void的指针和指向函数的指针上支持加法和减法运算。这是通过将空隙或函数的大小视为1来实现的。

    如果你需要你的代码是可移植的,坚持使用标准C总是一个好主意,但是如果你的代码只在一个特定的平台上运行,那么使用某些编译器扩展是没有害处的。

        3
  •  0
  •   david.pfx    10 年前

    C11标准n1570 S6.5.6/2:

    对于加法,两个操作数都应为算术类型,或者一个操作数应为 指针指向一个完整的对象类型,另一个对象类型应为整数类型。(递增为 相当于添加1。)

    C++的语言类似。

    这绝对不是符合标准的行为。我想GCC团队已经知道了这一点。

    答案是,兼容的编译器应该发出诊断,然后生成它喜欢(或不喜欢)的任何代码。