【问题标题】:Are these null pointers, or are they pointers to address 0?这些是空指针,还是指向地址 0 的指针?
【发布时间】:2013-05-09 21:51:29
【问题描述】:

如果我写

int zero = 0;

void *p1 = (void *)0;
void *p2 = (void *)(int)0;
void *p3 = (void *)(0 /*no-op, but does it affect the next zero?*/, 0);

void *p4 = (void *)zero;    // For reference, this is a pointer to address zero
void *p5 = 0;               // For reference, this is a null pointer
void *p6 = NULL;            // For reference, this is a null pointer
void *p7 = nullptr;         // For reference, this is a null pointer (C++11)

static const int static_zero_1 = 0;       // Is this a literal zero when used?
static const int static_zero_2 = 1 - 1;   // No "literals 0" per se... is it?
void *p8 = (void *)static_zero_1;   // I have seen weird substitution rules...
void *p9 = (void *)static_zero_2;   // do they apply for NULL too?

p1p2p3编辑:我添加了 p8p9)中的哪一个将是 空指针(即== NULL,可能是地址零,也可能不是),其中哪些是地址为零的指针(可能是== NULL,也可能不是== NULL)?

如果 C 和 C++ 的答案不同,它们各自的答案是什么?

【问题讨论】:

  • 空指针不就是“指向地址0”定义的吗?
  • @leemes:不,见this answer
  • @Andrew:我的意思是写我写的——你确定那也是 nullptr 吗?我的理解是它不是,因为它没有使用文字 0。
  • @Andrew 不要再猜测 Mehrdad - 他比那更聪明。
  • @Mehrdad 不,我的意思是 0(0, 0) 会有所不同,因为后者不是文字。幸运的是,我错了,事实并非如此 - 请参阅我的答案。

标签: c++ c null language-lawyer nullptr


【解决方案1】:

并且用 C 来完成安迪的答案:

From the C99 Standard:

6.3.2.3 指针

1 指向 void 的指针可以转换为指向任何不完整或对象的指针或从指针转换为指向任何不完整或对象的指针 类型。指向任何不完整或对象类型的指针可以转换为指向 void 的指针 又回来了;结果应与原始指针比较。

3 值为0 的整数常量表达式,或转换为类型的此类表达式 void *,称为空指针常量。 55) 如果一个空指针常量被转换为一个 指针类型,得到的指针,称为空指针,保证比较不相等 指向任何对象或函数的指针。

因此,任何计算结果为0整数常量表达式 都是空指针常量,可以转换为NULL 指针。实际上,在您的示例中,除了p4p8p9 之外的所有指针都是空指针。 p4p8p9 不必是空指针,因为它们的初始化不是常量表达式,因为它包含变量(即使 const 合格)。

Here's another answer about NULL in C++,记录在案。

【讨论】:

  • +1 一个整数常量表达式,其值为0,或者这样的表达式转换为类型void *...啊,我想这意味着它们是all 将是 C 中的空指针(p4 除外),嗯?
  • 现在有趣的是,如果我说const int zero = 0p4 仍然是地址零。但是如果我说static const int zero = 0,那么它就会变成一个空指针,对吧?! o_O
  • @Mehrdad 对,值得看一下标准的第 6.6 节,我刚刚找到了!确实,那里有对static 的引用(但是,这是在addressof 运算符的上下文中,略有不同)。
  • 在 C 中,p8p9 也不会被强制为空指针。这是因为术语“整数常量表达式”在 C 中有一个非常具体的定义,不包括 const 限定变量,因为它们用于初始化 p8p9
  • @Mehrdad 不。静态没有区别。
【解决方案2】:

p1p2 是空指针; p3 是实现定义的, 并且可能是别的东西。 (逗号运算符不能是 一个常量表达式。和一个非常数的映射 指针的整数值 0 是实现定义的。)C 是 与此处的 C++ 相同。

p8p9 在 C++ 中都是空指针,但在 C 中不是。

关于你对static_zero_2的评论,没有 在任何一种语言中都要求存在文字零, 任何地方。 g++ 将NULL定义为编译器内置__null, 例如,您可以使用(1 - 1),或'\0',或任何其他 常量表达式求值为 0。

【讨论】:

  • 我不明白为什么 p3 是实现定义的。标准在哪里说逗号运算符不能是常量表达式的一部分?
  • @AndyProwl in 6.6 "constant expressions", p3 "Constant Expressions shall not contain assignment, increment, decrement, function-call, or comma operators, ..."
  • @JensGustedt:那是 C,我说的是 C++11
  • @AndyProwl,啊,你没这么说,在 C++11 中你必须自己寻找,但很可能这是相似的。
  • 但是看到第 6.6 p 3 段它在“约束”部分,所以实际上这不是实现定义的。至少在 C 中,这不是一个常量表达式。
【解决方案3】:

p1p2p3 中的哪一个是空指针?

在 C++11 中,所有这些。根据 C++11 标准的第 4.10/1 段:

空指针常量是整数类型的整数常量表达式 (5.19) prvalue,其计算结果为 零或std::nullptr_t 类型的纯右值。 [...]

因此,根据标准的术语,所有是 constant(整数)表达式并计算结果为 0 的都是 空指针常量(不是空指针,但)。在您的示例中,唯一不是计算结果为0nullptr_t 类型的纯右值的常量表达式是zero,因为它不是常量表达式。

段落继续:

空指针常量可以转换为指针类型;这 结果是该类型的 空指针值,并且可以与对象指针的所有其他值或 函数指针类型。这种转换称为空指针转换。的两个空指针值 相同的类型应该比较相等。

因此,在您的示例中,除 p4 之外的所有指针都是 空指针值,并且它们之间比较相等。

【讨论】:

  • 哇,在 C++11 中这真的很简单! +1 谢谢,这至少回答了部分问题。
  • @Mehrdad:是的,我不是 C 人,所以我将把另一部分留给更有经验的人 ;)
  • @AndyProwl 我做到了——我省略了 C++ 部分,因为我不是 C++ 人:D
  • @H2CO3:哦,对,当然——我没看到你引用了 C99 标准;)干得好
  • p3 不是空指针常量,因为它不是常量表达式。 C++11 中的措辞更为复杂,但很明显,常量表达式是满足所有其他标准的“条件表达式”。 “条件表达式”不能包含逗号运算符(或任何赋值运算符)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-07
  • 1970-01-01
  • 2011-04-24
  • 2020-02-26
  • 2012-08-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多