gpt4 book ai didi

c - 理解空指针

转载 作者:太空狗 更新时间:2023-10-29 16:58:26 24 4
gpt4 key购买 nike

在我的answer我提到取消引用 void 指针是个坏主意。但是,当我这样做时会发生什么?

#include <stdlib.h>
int main (void) {
void* c = malloc(4);
*c;
&c[0];
}

编译:

gcc prog.c -Wall -Wextra
prog.c: In function 'main':
prog.c:4:2: warning: dereferencing 'void *' pointer
*c;
^~
prog.c:5:4: warning: dereferencing 'void *' pointer
&c[0];
^
prog.c:5:2: warning: statement with no effect [-Wunused-value]
&c[0];
^

这是一张来自 Wandbox 的图片,供那些说它没有发生的人使用:

enter image description here

和 Ideone 中的现场演示

它实际上会尝试读取c 指向的内存中有什么,然后获取该结果,但最后什么也没做?或者这一行根本没有效果(但是 GCC 不会产生警告)。

我在想,由于编译器对数据类型一无所知,所以在不知道类型大小的情况下,它无法做很多事情。

为什么取消引用 void* 不会产生错误,而只会产生警告?


如果我尝试赋值,我会得到一个错误:

invalid use of void expression

但是单独取消引用不应该产生错误吗?

最佳答案

C 标准在 5.1.1.3p1 中明确说明:

A conforming implementation shall produce at least one diagnostic message (identified in an implementation-defined manner) if a preprocessing translation unit or translation unit contains a violation of any syntax rule or constraint, even if the behavior is also explicitly specified as undefined or implementation-defined. Diagnostic messages need not be produced in other circumstances. 9)

用脚注 9 表示

The intent is that an implementation should identify the nature of, and where possible localize, each violation. Of course, an implementation is free to produce any number of diagnostics as long as a valid program is still correctly translated. It may also successfully translate an invalid program.

因此,GCC 完全符合 C 标准。您的程序是无效程序。只需要一条诊断消息 - 允许编译器成功翻译您的无效程序。由于 GCC 对 void pointer arithmetic 有一个非标准扩展:

In GNU C, addition and subtraction operations are supported on pointers to void and on pointers to functions. This is done by treating the size of a void or of a function as 1.

A consequence of this is that sizeof is also allowed on void and on function types, and returns 1.

The option -Wpointer-arith requests a warning if these extensions are used.

它决定它可以对您的无效程序做一些“明智”的事情并成功翻译它。


请注意 pointer-to-void 的非求值取消引用在 sizeof 中已经是必需的,因为:

void *foo;
sizeof *foo;

必须匹配

sizeof (void);

它们的计算结果都为 1,因此允许丢弃指向 void everywhere 的指针的取消引用会更容易。


正如 Lundin 所说,如果您想要实际的约束违规错误,请使用 -std=c11 -pedantic-errors

关于c - 理解空指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46241035/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com