空指针上的地址计算是否在C++中定义行为?这是一个简单的示例程序。
struct A { int x; };
int main() {
A* p = nullptr;
&(p->x); // is this undefined behavior?
return 0;
}
谢谢。
编辑下标在另一个问题中。
&(p->x); // is this undefined behavior?
Standard对此有点模糊:
[参考资料] ...表达式 E1->E2 将转换为等效形式 (*(E1((。E2;
[expr.unary.op] 一元 * 运算符 ...结果是一个引用对象的左值...表达式指向的。
本节中没有明确提及UB。引用的规则似乎与空指针不指向任何对象的事实相冲突。这可以解释为是的,行为是不确定的。
[expr.unary.op] 一元和运算符的结果是指向其操作数的指针。如果操作数是 T 类型的左值,则生成的表达式是类型为"指向 T 的指针"的 prvalue,其结果是指向指定对象的指针 ([intro.memory](。
同样,不存在指定的对象。请注意,操作数左值永远不会转换为右值,这肯定是 UB。
早在 2000 年,就存在 CWG 问题,以澄清通过 null 的间接寻址是否未定义。拟议的决议(2004年(将澄清通过null的间接寻址不是UB,但到目前为止似乎尚未添加到标准中。
但是,它是否是 UB 并不重要,因为您不需要这样做。至少,生成的指针将是无效的,因此是无用的。
如果您计划将指针转换为整数以获取成员的偏移量,则无需执行此操作,因为您可以改用标准库中的offsetof
宏,该库没有 UB。
&(p[1]); // undefined?
在这里,行为显然是未定义的:
<小时 />[前子] ...表达式 E1[E2] 与 *(((E1(+(E2(( 相同(根据定义(,只是在数组操作数的情况下,如果该操作数是左值,则结果为左值,否则为 x值。
[expr.add] 当将具有整型的表达式 J 添加到指针类型的表达式 P 或从中减去时,结果的类型为 P。
如果 P 的计算结果为空指针值,J 的计算结果为 0(不适用(
否则,如果 P 指向数组元素(不适用(
否则,行为是未定义的。
&(p[0]); // undefined?
根据以前的规则,第一个选项适用:
如果 P 的计算结果为空指针值,J 的计算结果为 0,则结果为空指针值。
现在我们回到通过此空值的间接寻址是否为 UB 的问题。请参阅答案的开头。
不过,这并不重要。没有必要写这个,因为这简直是不必要的复杂sizeof(int) * i
写法(i
分别为 1 和 0(。