是否通过C99标准成功编译*(NULL)?

时间:2013-10-17 16:44:55

标签: c c99

我理解这个代码永远不应该被执行,但是*(NULL)是否可以通过C99标准成功编译?

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

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

3 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分:4)

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

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

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

答案 2 :(得分:0)

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

从马口:

  

(C99,6.5.3.2.p4)“如果为指针指定了无效值,则unary *运算符的行为未定义.87)”

并且(强调我的):

  

87):“ unary *运算符解除引用指针的无效值是空指针,地址与指向的对象类型不一致,地址对象在它的一生结束之后。“

当然,NULL是一个空指针:

  

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

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