解引用空指针

int* p = 0; int* q = &*p; 

这是不确定的行为吗? 我浏览了一些相关的问题,但是这个具体方面没有显示出来。

这个问题的答案是:它取决于你使用哪种语言标准:-)。

在C90和C ++中,这是无效的,因为您对空指针执行间接寻址(通过执行*p ),这样做会导致未定义的行为。

但是,在C99中,这有效的,格式良好的,而且是明确的。 在C99中,如果作为应用一元语法*或通过执行下标( [] )的结果获得一元操作数& ,那么&也不应用*[] 。 例如:

 int* p = 0; int* q = &*p; // In C99, this is equivalent to int* q = p; 

同样,

 int* p = 0; int* q = &p[0]; // In C99, this is equivalent to int* q = p + 0; 

从C99§6.5.3.2/ 3开始:

如果[一元&运算符]的操作数是一元运算符*的结果,那么运算符和&运算符都不会被计算,结果就好像两个都被省略一样,除了运算符上的约束仍然适用,结果不是左翼

类似地,如果操作数是[]运算符的结果,则评估[]所隐含的&运算符和一元运算符* ,结果就好像&运算符被删除, []运算符被更改为一个+运算符。

(及其脚注#84):

因此, &*E相当于E (即使E是一个空指针)

是的,这将是未定义的行为,但您的编译器可能会优化&*出。

为什么它没有定义,是因为你试图访问可寻址空间之外的内存。

是的,解引用空指针是未定义的行为。 指针上下文中的整数常量0是空指针。 而已。

现在,如果你的第二行是int *q = p; 这将是一个简单的指针分配。 如果编译器删除&*并将取消引用减less到一个赋值,那么你没问题。

恕我直言,就两条代码行而言,地址空间之外没有任何访问权限。 第二种说法是简单地把(* p)的地址再次写成'p',因此它将存储'0'。 但是这个位置永远不会被访问