标准说取消引用空指针会导致未定义的行为。但是什么是“空指针”?在下面的代码中,我们称之为“空指针”:
struct X
{
static X* get() { return reinterpret_cast<X*>(1); }
void f() { }
};
int main()
{
X* x = 0;
(*x).f(); // the null pointer? (1)
x = X::get();
(*x).f(); // the null pointer? (2)
x = reinterpret_cast<X*>( X::get() - X::get() );
(*x).f(); // the null pointer? (3)
(*(X*)0).f(); // I think that this the only null pointer here (4)
}
我的想法是,仅在最后一种情况下才会取消引用空指针。我对吗?根据C ++标准,编译时空指针和运行时之间是否存在差异?
答案 0 :(得分:12)
只有第一个和最后一个是空指针。其他是reinterpret_cast
的结果,因此对实现定义的指针值进行操作。是否为它们定义了行为取决于您转换到的地址是否有对象。
答案 1 :(得分:12)
计算结果为0的整型常量表达式作为空指针有效,因此第一种情况也是取消引用空指针。
通过某种算术运算设置为0的指针不一定是空指针。在大多数实现中,它的行为方式与空指针相同,但标准不保证这一点。
答案 2 :(得分:7)
C ++ Standard(2003)4.10
4.10指针转换
1空指针常量是一个 积分常数表达式(5.19) 求值的整数类型的右值 为零。空指针常量可以 被转换为指针类型;该 result是空指针值 那种类型,可以区分 指向对象的每个其他值 或指向函数类型的指针。两个空 相同类型的指针值 比较平等。一个转换 null指针常量指向 cv-qualified类型是单一的 转换,而不是a的顺序 指针转换后跟一个 资格转换(4.4)。
5.2.10重新解释投射
注64)转换积分常数 表达式(5.19),值为零 总是产生一个空指针(4.10), 但转换其他表达 碰巧有零价值需求 不产生空指针。
1)X* x = 0; (*x).f();
是的。
0是整数常量表达式,并转换为空指针常量。
然后可以将空指针常量转换为空指针值。
2)x = X::get();
否,见5.2.10中的注释64
3)x = reinterpret_cast<X*>( X::get() - X::get() );
否,见5.2.10中的注释64
4)((X )0).f();是。 0(积分常数表达式) - &gt;空指针常量 - &gt; 空指针值。
答案 3 :(得分:0)
X* x = 0;
(*x).f(); // the null pointer? (1)
我认为这有资格作为取消引用,即使f()
从未实际使用this
指针,并且X
中没有虚拟方法。我的反应是说这是一次崩溃,但现在我想到了,我不太确定。
x = X::get();
(*x).f(); // the null pointer? (2)
可能是指针无效。不确定它是否会崩溃(见上文的推理)。
x = reinterpret_cast<X*>( X::get() - X::get() );
(*x).f(); // the null pointer? (3)
表达式X::get() - X::get()
是否编译?我不认为从另一个指针中减去指针是合法的。