是否对 C++ 中定义的空指针进行成员访问?
Is member access on a null pointer defined in 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?
标准对此有点模糊:
[expr.ref] ... The expression E1->E2 is converted to the equivalent form (*(E1)).E2;
[expr.unary.op] The unary * operator ... the result is an lvalue referring to the object ... to which the expression points.
该部分没有明确提及 UB。引用的规则似乎与空指针不指向任何对象这一事实相冲突。这可以解释为是的,行为未定义。
[expr.unary.op] The result of the unary & operator is a pointer to its operand. ... if the operand is an lvalue of type T, the resulting expression is a prvalue of type “pointer to T” whose result is a pointer to the designated object ([intro.memory]).
同样,不存在指定的对象。请注意,操作数左值绝不会转换为右值,这肯定是 UB。
早在 2000 年就有 CWG issue 阐明通过 null 的间接寻址是否未定义。提议的决议 (2004) 阐明通过 null 的间接寻址是 not UB,似乎 not 到目前为止已添加到标准中。
然而,它是否是 UB 并不重要,因为您不需要这样做。至少,结果指针将是无效的,因此无用。
如果您打算将指针转换为整数以获取成员的偏移量,则无需执行此操作,因为您可以使用标准库中的 offsetof
宏,它不会没有UB。
&(p[1]); // undefined?
在这里,行为很明显是未定义的:
[expr.sub] ... The expression E1[E2] is identical (by definition) to *((E1)+(E2)), except that in the case of an array operand, the result is an lvalue if that operand is an lvalue and an xvalue otherwise.
[expr.add] When an expression J that has integral type is added to or subtracted from an expression P of pointer type, the result has the type of P.
If P evaluates to a null pointer value and J evaluates to 0 (does not apply)
Otherwise, if P points to an array element (does not apply)
Otherwise, the behavior is undefined.
&(p[0]); // undefined?
根据之前的规则,第一个选项适用:
If P evaluates to a null pointer value and J evaluates to 0, the result is a null pointer value.
现在我们又回到了通过这个 null 间接寻址是否是 UB 的问题。见答案开头。
不过,这并不重要。没有必要写这个,因为这是写 sizeof(int) * i
的简单不必要的复杂方式(i
分别为 1 和 0)。
地址计算是否基于 C++ 中的空指针定义行为?这是一个简单的示例程序。
struct A { int x; };
int main() {
A* p = nullptr;
&(p->x); // is this undefined behavior?
return 0;
}
谢谢。
编辑 下标包含在
&(p->x); // is this undefined behavior?
标准对此有点模糊:
[expr.ref] ... The expression E1->E2 is converted to the equivalent form (*(E1)).E2;
[expr.unary.op] The unary * operator ... the result is an lvalue referring to the object ... to which the expression points.
该部分没有明确提及 UB。引用的规则似乎与空指针不指向任何对象这一事实相冲突。这可以解释为是的,行为未定义。
[expr.unary.op] The result of the unary & operator is a pointer to its operand. ... if the operand is an lvalue of type T, the resulting expression is a prvalue of type “pointer to T” whose result is a pointer to the designated object ([intro.memory]).
同样,不存在指定的对象。请注意,操作数左值绝不会转换为右值,这肯定是 UB。
早在 2000 年就有 CWG issue 阐明通过 null 的间接寻址是否未定义。提议的决议 (2004) 阐明通过 null 的间接寻址是 not UB,似乎 not 到目前为止已添加到标准中。
然而,它是否是 UB 并不重要,因为您不需要这样做。至少,结果指针将是无效的,因此无用。
如果您打算将指针转换为整数以获取成员的偏移量,则无需执行此操作,因为您可以使用标准库中的 offsetof
宏,它不会没有UB。
&(p[1]); // undefined?
在这里,行为很明显是未定义的:
[expr.sub] ... The expression E1[E2] is identical (by definition) to *((E1)+(E2)), except that in the case of an array operand, the result is an lvalue if that operand is an lvalue and an xvalue otherwise.
[expr.add] When an expression J that has integral type is added to or subtracted from an expression P of pointer type, the result has the type of P.
If P evaluates to a null pointer value and J evaluates to 0 (does not apply)
Otherwise, if P points to an array element (does not apply)
Otherwise, the behavior is undefined.
&(p[0]); // undefined?
根据之前的规则,第一个选项适用:
If P evaluates to a null pointer value and J evaluates to 0, the result is a null pointer value.
现在我们又回到了通过这个 null 间接寻址是否是 UB 的问题。见答案开头。
不过,这并不重要。没有必要写这个,因为这是写 sizeof(int) * i
的简单不必要的复杂方式(i
分别为 1 和 0)。