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

如果我写

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 ++中有所不同,那么它们中的每一个是什么?

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

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

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

并用C完成Andy的答案:

从C99标准 :

6.3.2.3指针

1指向void的指针可以转换为指向任何不完整或对象类型的指针。 指向任何不完整或对象类型的指针可能会转换为指向void的指针并再次返回; 结果应该等于原始指针。

3 值为0整型常量表达式或类型为void *的表达式称为空指针常量 。 55)如果将空指针常量转换为指针类型,则保证将结果指针(称为空指针)与指向任何对象或函数的指针进行比较。

因此,任何求值为0 整型常量表达式都是空指针常量,可以转换为NULL指针。 在你的例子中,除了p4p8p9之外的所有指针都是空指针。 p4p8p9不需要是空指针,因为它们的初始化不是常量表达式,因为它包含变量(即使const限定)。

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

p1p2p3哪一个是空指针?

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

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

因此,根据标准的术语,作为常量 (整数)表达式并且求值为0都是空指针常量 (还不是空指针 )。 唯一不是求值为0的常量表达式或示例中类型为nullptr_t的prvalue的值zero ,因为它不是常量表达式。

该段继续:

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

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