18

如果我写

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)?

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

4

3 回答 3

9

为了让安迪的答案用 C 完成:

来自 C99 标准

6.3.2.3 指针

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

3具有值的整型常量表达式0,或这种类型转换的表达式 void *,称为空指针常量。55) 如果将空指针常量转换为指针类型,则生成的指针(称为空指针)保证与指向任何对象或函数的指针不相等。

因此,任何计算结果为的整数常量表达式0都是空指针常量,并且可以转换为NULL指针。实际上,在您的示例中,通过 except 和的所有指针p4都是p8p9指针。p4,p8并且p9不必是空指针,因为它们的初始化不是常量表达式,因为它包含变量(即使const合格)。

NULL这是关于in C++的另一个答案,供记录。

于 2013-05-15T11:07:55.877 回答
8

p1p2和中的哪一个p3是空指针?

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

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

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

该段继续:

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

因此,在您的示例中,除了空指针值p4之外的所有指针都比较相等。

于 2013-05-15T11:05:19.920 回答
8

p1并且p2是空指针;p3是实现定义的,可能是别的东西。(逗号运算符不能是常量表达式的一部分。非常量整数值 0 到指针的映射是实现定义的。)C 在这里与 C++ 相同。

p8并且p9在 C++ 中都是空指针,但在 C 中不是。

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

于 2013-05-15T12:08:15.967 回答