1

我知道这段代码永远不应该被执行,但是*(NULL)按照 C99 标准编译成功了吗?

#include <stdio.h>
int main(void) {
    *(NULL);
    return 0;
}

PS:在ideone上运行它返回0,但我不知道正在使用的编译器版本:(

4

3 回答 3

5

如果NULL定义为简单0(允许),则*(0)违反约束,必须进行诊断。如果NULL定义为((void *)0)then*((void *)0)调用未定义的行为(通过取消引用空指针)并且编译器不需要发出任何诊断,但程序也不需要按照您期望的方式运行。

于 2013-10-17T17:15:22.890 回答
4

*(NULL)总是违反约束。*(NULL)作为一个完整的表达式在 C 中的任何定义下都是“不可编译的” NULLNULL可以定义一个整数零,这显然是不可解引用的。NULL可以定义为整数零转换为void *类型,但void *在 C 中取消引用指针是非法的。

注意:我仍然不完全确定我上面关于取消引用void *指针的陈述是否正确。是否违反约束?该标准没有明确说明。但同时它只定义了*指向函数的指针和指向对象的指针的一元行为。同时,void不是对象类型。

void *如果取消引用指针确实是合法的,那么*(NULL)它本身就会产生未定义的行为(假设(void *) 0定义NULL)。但仍有一个上下文*(NULL)可能作为子表达式有效。它是&*(NULL)。该语言对组合进行了特殊处理&*,使其成为具有明确行为的无操作,即使在*单独会产生未定义行为的情况下也是如此。

于 2013-10-17T17:23:15.507 回答
0

*(NULL)是未定义的行为。

从马口:

(C99, 6.5.3.2.p4) “如果一个无效值被分配给指针,一元 * 操作符的行为是未定义的。87)”

并且(强调我的):

87):“一元 * 运算符取消引用指针的无效值包括空指针、与指向的对象类型不恰当对齐的地址,以及对象生命周期结束后的地址。”

当然,NULL是一个空指针:

(C99,7.17p3)“宏 [..] NULL 扩展为实现定义的空指针常量;”

与调用未定义行为的所有程序一样,编译器有权不编译它(参见 C99,3.4.3p2)。

于 2013-10-17T17:12:36.553 回答