int* p = 0;
int* q = &*p;
这是未定义的行为吗?我浏览了一些相关问题,但这个具体方面没有显示出来。
答案 0 :(得分:50)
这个问题的答案是:它取决于你遵循的语言标准: - )。
在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
是空指针)
答案 1 :(得分:3)
是的,这将是未定义的行为,但您的编译器可能会优化&*
。
为什么它未定义,是你试图访问可寻址空间之外的内存。
答案 2 :(得分:-1)
是的,取消引用空指针是未定义的行为。指针上下文中的整数常量0是空指针。就是这样。
现在,如果您的第二行是int *q = p;
,那将是一个简单的指针赋值。如果编译器删除了&*
并减少了对赋值的取消引用,那么你就可以了。
答案 3 :(得分:-1)
恕我直言,就这两个代码行而言,地址空间之外没有任何访问权限。第二个陈述只是取(* p)的地址再次为'p',因此它将存储'0'。但该位置永远不会访问。