其中哪一个会创建空指针?

发布于 2024-08-26 15:09:49 字数 527 浏览 13 评论 0原文

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

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

The standard says that dereferencing the null pointer leads to undefined behaviour. But what is "the null pointer"? In the following code, what we call "the 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)
}

My thought is that dereferencing of the null pointer takes place only in the last case. Am I right? Is there difference between compile time null pointers and runtime according to C++ Standard?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

邮友 2024-09-02 15:09:49

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

Only the first and the last are null pointers. The others are results of reinterpret_cast and thus operate on implementation defined pointer values. Whether the behavior is undefined for them depends on whether there is an object at the address you casted to.

栀子花开つ 2024-09-02 15:09:49

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

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

An integer constant expression that evaluates to 0 is valid as a null pointer, so the first case is also dereferencing a null pointer.

A pointer which is set to 0 via some arithmetic calculation is not necessarily a null pointer. In most implementations it will behave in the same way as a null pointer, but this is not guaranteed by the standard.

故事还在继续 2024-09-02 15:09:49

C++ 标准 (2003) 4.10

4.10 指针转换

1 空指针常量是
积分常量表达式 (5.19)
计算的整数类型的右值
为零。空指针常量可以
转换为指针类型;这
结果是空指针值
该类型可区别于
指向对象的指针的每个其他值
或指向函数类型的指针。两个空
相同类型的指针值应
比较相等。的转换
指向指针的空指针常量
cv 限定类型是单一的
转换,而不是 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::get() - X: :get() ); 否,参见 5.2.10 中的注释 64

4) ((X)0).f();是的。
0(积分常量表达式)-->空指针常量 -->
空指针值。

C++ Standard (2003) 4.10

4.10 Pointer conversions

1 A null pointer constant is an
integral constant expression (5.19)
rvalue of integer type that evaluates
to zero. A null pointer constant can
be converted to a pointer type; the
result is the null pointer value of
that type and is distinguishable from
every other value of pointer to object
or pointer to function type. Two null
pointer values of the same type shall
compare equal. The conversion of a
null pointer constant to a pointer to
cv-qualified type is a single
conversion, and not the sequence of a
pointer conversion followed by a
qualification conversion (4.4).

5.2.10 Reinterpret cast

Note 64) Converting an integral constant
expression (5.19) with value zero
always yields a null pointer (4.10),
but converting other expressions
that happen to have value zero need
not yield a null pointer.

1) X* x = 0; (*x).f(); Yes.
0 is integral constant expression and is converted to the null pointer constant.
Then null pointer constant can be converted to the null pointer value.

2) x = X::get(); no, see note 64 in 5.2.10

3) x = reinterpret_cast<X*>( X::get() - X::get() ); no, see note 64 in 5.2.10

4) ((X)0).f(); Yes.
0 (integral constant expression) --> the null pointer constant -->
the null pointer value.

我很坚强 2024-09-02 15:09:49
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() 是否可以编译?我认为像这样从另一个指针中减去一个指针是不合法的。

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

X* x = 0;
(*x).f(); // the null pointer?  (1)

I think this qualifies as dereference, even though f() never actually uses the this pointer, and there are no virtual methods in X. My reflex was to say that this is a crash, but now that I think of it, I'm not so sure.

x = X::get();
(*x).f(); // the null pointer?  (2)

Probably an invalid pointer. not sure whether it will crash (see above for reasoning).

x = reinterpret_cast<X*>( X::get() - X::get() );
(*x).f(); // the null pointer?  (3)

Does the expression X::get() - X::get() compile? I didn't think it was legal to subtract a pointer from another pointer like that.

EDIT: D'oh! Of course it's legal. What was I thinking? Clearly, I am a maroon.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文