这些空指针,还是地址为0的指针?

时间:2013-05-15 10:50:30

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

如果我写

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)中的哪一个< em>空指针(即== NULL,可能是也可能不是地址为零),以及哪些是地址为零的指针(可能是也可能不是== NULL)?< / p>

如果答案在C和C ++中有所不同,那么它们中的每一个是什么?

3 个答案:

答案 0 :(得分:9)

让Andy的答案完成C:

From the C99 Standard

  

6.3.2.3指针

     

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

     

3 整数常量表达式,其值为0 ,或者这样的表达式强制转换为类型   void *被称为空指针常量。   55)如果空指针常量转换为a   指针类型,结果指针,称为空指针,保证比较不等   指向任何对象或函数的指针。

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

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

答案 1 :(得分:8)

  

p1p2p3中哪些是空指针?

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

  

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

因此,根据标准的术语,所有常量(整数)表达式并且评估为0的是空指针常量(还不是空指针。在示例中,唯一不是常量表达式(0或prvalue类型nullptr_t的{​​{1}}是zero,因为它不是常量表达式。

该段继续:

  

空指针常量可以转换为指针类型;该   result是该类型的空指针值,并且可以与对象指针的每个其他值区分开来   函数指针类型。这种转换称为空指针转换。两个空指针值   相同类型应相等。

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

答案 2 :(得分:8)

p1p2是空指针; p3是实现定义的, 并可能是别的东西。 (逗号运算符不能成为其中的一部分 一个恒定的表达。并且映射为非常数 指针的整数值0是实现定义的。)C是 这里与C ++相同。

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

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