以下哪个会创建空指针?

时间:2010-03-24 22:32:12

标签: c++ dereference null-pointer

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

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 个答案:

答案 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()是否编译?我不认为从另一个指针中减去指针是合法的。

编辑:D'哦!当然这是合法的。我在想什么?显然,我是一个栗色的人。