为什么GCC不接受void-pointer算法被认为是一个错误?

时间:2014-08-19 03:23:15

标签: c pointers gcc ansi

至少有三篇关于如何在C中禁止无效指针算术的帖子; gcc 4.8.2允许它,假设void是字节大小;以及如何打开额外的迂腐警告以触发错误。这是一个例子:

#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没有发出编译错误,至少它可能会发出一个&#34;弃用的#34;使用默认编译器标志进行警告。而且,即使有 -Wall,它甚至没有发出警告。咦?这让我感到惊讶,因为gcc看起来非常成熟,而C并不是一种新颖或复杂的语言。

3 个答案:

答案 0 :(得分:12)

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

默认情况下,

gcc不会对void*上的指针算法发出警告。这意味着默认情况下,gcc 不是符合C的编译器

有人可能会认为这是一个错误,但在默认模式下,gcc不是标准C的编译器,而是GNU C.(Fortran编译器未能成为符合标准的C编译器也不是错误。)

精心选择的命令行选项可以强制gcc至少尝试符合要求。例如:

gcc -std=cXX -pedantic

其中XX909911之一,会导致gcc警告void*上的指针算术。用-pedantic替换-pedantic-errors会导致它将此类算法视为致命错误。

答案 1 :(得分:2)

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

在这种情况下,来自https://gcc.gnu.org/onlinedocs/gcc/Pointer-Arith.html

  

在GNU C中,指向void的指针和指向函数的指针都支持加法和减法操作。这是通过将空白或函数的大小视为1来完成的。

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

答案 2 :(得分:0)

C11标准n1570 S6.5.6 / 2:

  

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

C ++的语言类似。

它绝对不符合标准的行为。我认为GCC团队已经知道了。

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