2010-03-24 12 views
14

该标准指出,解除引用空指针会导致未定义的行为。但什么是“空指针”?在下面的代码,我们称之为“空指针”:其中哪些会创建一个空指针?

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

这不是一个家庭作业。 C++标准没有太多关于解引用空指针的信息。我只是想知道。 – 2010-03-24 22:41:10

+0

我在这里的答案的第一部分谈到了解引用空指针:http://stackoverflow.com/questions/2474018/when-does-invoking-a-member-function-on-a-null-instance-result-in- undefined-behav(我爱这个问题) – GManNickG 2010-03-24 22:43:46

回答

12

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

+0

解引用空指针和一些无效指针有什么区别? – 2010-03-24 22:45:06

+0

@Johannes:他们是空指针,但他们会导致核心转储?起初我是这么认为的,但经过一番考虑,我不太确定。看到我上面的答案。 – 2010-03-24 22:45:52

+2

@Scott Smith:它的实现已定义。特别是在没有“核心”概念的平台上,即UNIX以外的任何平台。 – 2010-03-25 02:54:11

12

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

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

+1

“将值为零的整型常量表达式(5.19)转换总会产生一个空指针(4.10),但转换碰巧具有零值的其他表达式不需要产生空指针”(5.2.10/5注64)。 – 2010-03-24 23:12:59

+1

@James Ahh!所以对于非常大的0值,0!= NULL! – Earlz 2010-03-24 23:22:48

+1

@Earlz:但是0!是1! – GManNickG 2010-03-24 23:29:55

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

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

+0

关于在空实例上调用非静态函数:导致未定义的行为。所以所有的赌注都很明显。也就是说,在实践中,只要不需要'this'指针(没有虚函数,没有成员等),那么它就不会崩溃,因为它从来没有被使用过。 – GManNickG 2010-03-24 22:48:32

+0

减去指针是很常见的 - 它会返回两个指针之间的差异。但是,因为这些不在同一个数组中,所以你是对的 - 结果未定义。 (但它可能编译) – pm100 2010-03-24 22:55:07

+0

@斯科特史密斯,我刚刚在GNU C++编译并执行没有错误。你为什么认为减去指针是非法的?我的第一个想法是OP问题中的代码将在(2)中崩溃。 – 2010-03-24 22:56:24

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();无参见注释64在5.2.10

3)x = reinterpret_cast<X*>(X::get() - X::get());没有,见注64 5.2.10

4)((X)0).F() ;是。 0(整型常量表达式) - >空指针常量 - > 空指针值。

+0

对于5.2.10中的脚注,还请注意http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#463中的缺陷报告 – 2010-03-25 09:02:40