13

该标准说取消引用空指针会导致未定义的行为。但什么是“空指针”?在下面的代码中,我们称之为“空指针”:

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++ 标准,编译时空指针和运行时之间有区别吗?

4

4 回答 4

12

只有第一个和最后一个是空指针。其他的是结果,reinterpret_cast因此对实现定义的指针值进行操作。他们的行为是否未定义取决于您投射到的地址是否有对象。

于 2010-03-24T22:36:10.620 回答
12

计算结果为 0 的整数常量表达式作为空指针是有效的,因此第一种情况也是取消引用空指针。

通过某种算术计算设置为 0 的指针不一定是空指针。在大多数实现中,它的行为方式与空指针相同,但标准不保证这一点。

于 2010-03-24T22:36:17.093 回答
7

C++ 标准 (2003) 4.10

4.10 指针转换

1 空指针常量是整数类型的整数常量表达式 (5.19) 右值,其计算结果为零。空指针常量可以转换为指针类型;结果是该类型的空指针值,并且可以与指向对象的指针或指向函数类型的指针的所有其他值区分开来。相同类型的两个空指针值应比较相等。将空指针常量转换为指向 cv 限定类型的指针是一次转换,而不是指针转换后跟限定转换 (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(整数常量表达式)--> 空指针常量--> 空指针值。

于 2010-03-25T08:53:51.693 回答
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()编译?我认为从这样的另一个指针中减去一个指针是不合法的。

编辑:哦!当然是合法的。我在想什么?很明显,我是栗色的。

于 2010-03-24T22:38:39.807 回答