成员访问是否在空指针上定义C++?



空指针上的地址计算是否在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(。

最新更新