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

问题描述 投票:0回答:3

这个问题在这里已有答案:

关于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没有发出编译错误,至少它可以使用默认编译器标志发出“已弃用”警告。而且,即使使用-Wall,它仍然没有发出警告。咦?这让我感到惊讶,因为gcc看起来非常成熟,而C并不是一种新颖或复杂的语言。

c pointers gcc ansi
3个回答
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会导致它将这种算法视为致命错误。


2
投票

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

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

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

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


0
投票

C11标准n1570 S6.5.6 / 2:

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

C ++的语言类似。

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

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

© www.soinside.com 2019 - 2024. All rights reserved.