这是一个nullptr吗?

5
阅读这篇问答时,我认为即使x0p也不应该是nullptr。我的理解是否正确?
int main()
{
    int x = 0;

    std::cin >> x; // Enter `0`

    void *p = (void *)x; // or: void *p = reinterpret_cast<void*>(x);


    if (!p)
        std::cout << "p is nullptr" << std::endl;
}

在标准输入中输入0后,我的GCC会显示消息“p is nullptr”。根据链接,它不应该被评估为nullptr,但结果与我的预期不同。
这段代码是未定义行为还是未指定的结果?为什么它会被评估为nullptr?

2
你将一个值为0的int强制转换为void *指针(实际上可能只是一个更宽的int),但其值仍为0。你期望p有什么值? - lc.
2
if语句实际上是在测试p == 0,这当然是成立的。而0是否等于nullptr则是一个更有趣的问题(VC++2012表示它们相等,但这是否有意义就不得而知了)。 - dlf
什么是nullptr?你是在谈论C++/CLI吗?NULL就像零一样,有些C++编程人员甚至避免使用NULL,因为它太不确定了(相反,他们会测试0或0L)。 - user645280
@JanHudec 当然,只是提供一个数据点。 - dlf
1
@dlf 实际上恰恰相反。根据定义,0 == nullptr。问题仅在于将 int 类型的 0 强制转换为指针后是否也相等。在 OP 的代码中似乎是这样的,但有些例子(尽管我现在找不到链接)表明这并非总是正确的(即空指针由非零位模式表示)。 - Konrad Rudolph
显示剩余10条评论
3个回答

11

C++11 5.2.10/5 Reinterpret cast [expr.reinterpret.cast](重点添加):

整型或枚举类型的值可以显式转换为指针。将指针转换为足够大的整数(如果实现中存在此类整数),然后再转换回相同的指针类型,其原始值将保持不变;除此之外,指针和整数之间的映射是由实现定义的。

5.2.10/4 中的相关内容:

std::nullptr_t 类型的值可以转换为整数类型;该转换与将(void*)0 转换为整数类型具有相同的含义和有效性。【注意:reinterpret_cast 不能用于将任何类型的值转换为 std::nullptr_t 类型。—end note】


2

让我们来回答你的问题:

如果 int x = 0,那么reinterpret_cast<void*>(x) != nullptr是可能的。但这不是必然的。实际上,在大多数平台上,reinterpret_cast<void*>(x) == nullptr ,但取决于哪个结果都是未定义行为。


2
ISO/IEC 14882:2011 §4.10/1 (以及成员指针的§4.11/1)仅表示,一个“整型常量表达式的prvalue值为0”的常量整数表达式是空指针常量。对于整数值,唯一的要求在于§5.2.10/5中,其中表示:“将指针转换为足够大小的整数(如果实现上有这样的整数),并将其转回相同的指针类型,将具有其原始值;指针和整数之间的映射是由实现定义的。”因此,整数值0是否转换为空指针也是由实现定义的。在大多数实现中,它会转换为null指针,因为这样更容易。

在第一句中复制粘贴错误了吗?“a constant integer expression that integral constant expression” 看起来不对。 “常量整数表达式”和“整型常量表达式”这两个短语有些混淆了。 - nobody

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接