取消引用空指针

fre*_*low 24 c c++ null pointers

int* p = 0;
int* q = &*p;
Run Code Online (Sandbox Code Playgroud)

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

Jam*_*lis 50

这个问题的答案是:它取决于你遵循的语言标准:-).

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

但是,在C99中,这有效的,格式良好且定义明确的.在C99中,如果unary-的操作数&作为应用unary-的结果获得*或通过进行下标([]),则无论是&也不*[]施加.例如:

int* p = 0;
int* q = &*p; // In C99, this is equivalent to int* q = p;
Run Code Online (Sandbox Code Playgroud)

同样,

int* p = 0;
int* q = &p[0]; // In C99, this is equivalent to int* q = p + 0;
Run Code Online (Sandbox Code Playgroud)

从C99§6.5.3.2/ 3:

如果[一元运算&符] 的操作数是一元运算符的结果*,则不会对该运算符和&运算符进行求值,结果就好像两者都被省略,除了对运算符的约束仍然适用且结果不是左值.

类似地,如果操作数是[]运算符的结果,&则不会对运算符或*由其暗示的一元[]进行求值,结果就像&删除了[]运算符并将运算符更改为+运算符一样.

(及其脚注,#84):

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

  • 特别注意"3.8/5"的措辞,其中说"这样的指针可以被解除引用但是得到的左值只能以有限的方式使用,如下所述." 以及明确"解除引用"的各种注释适用于将地址转换为左值.将左值变换为右值的另一个动作不称为解除引用,但它被称为左值到右值的转换,或者只是"访问存储的值"(如3.10/15中所示)等. (2认同)