解引用空指针
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'。 但是这个位置永远不会被访问 。