5

Reading this Q&A, I thought p shouldn't be a nullptr even if x is 0. Have I understood it right?

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;
}

After entering 0 in the standard input, the message p is nullptr will be shown in my GCC. According to the link, it shouldn't evaluate to nullptr, but the result is not as my expectation.

Is the code undefined behavior? or unspecified result? Why does it evaluate to nullptr?

Community
  • 1
  • 1
masoud
  • 55,379
  • 16
  • 141
  • 208
  • 2
    You're casting an `int` which has a value of 0 to a `void *` pointer (which for all intents and purposes may as well just be a glorified and possibly wider int) - still with the value of 0. What value did you expect `p` to have? – lc. May 13 '14 at 18:33
  • 2
    The `if` is really testing whether p == 0, which of course it does. Whether 0 == nullptr is a more interesting question (VC++2012 says it does, for what that's worth). – dlf May 13 '14 at 18:34
  • What is `nullptr` are you talking C++/CLI here? `NULL` is as zero as zero gets, some C++ coders eschew even using `NULL` because it's too indeterminate (instead they test for 0 or 0L). –  May 13 '14 at 18:34
  • @dlf: What VC++2012 says is irrelevant. What the _specification_ says is. – Jan Hudec May 13 '14 at 18:34
  • @JanHudec Absolutely; just providing a data point. – dlf May 13 '14 at 18:35
  • 1
    @dlf No actually it’s the other way round. `0 == nullptr`, by definition. The question is solely whether an `int` `0`, cast to a pointer, equals that, too. In OP’s code it appears to be, but there are examples (although I can’t find a link now) where that isn’t the case (i.e. where a null pointer is represented by a non-zero bit pattern). – Konrad Rudolph May 13 '14 at 18:36
  • @ebyrob `nullptr` is the new `NULL` for C++ (and is not a `#define`). – crashmstr May 13 '14 at 18:36
  • @MM. see my answer below. The standard say `nullptr` is not necessarily zero; it does not say that `nullptr` is necessarily not zero. :D – Massa May 13 '14 at 18:38
  • Why are you converting to `void*` and not `nullptr_t`? – Sergey Kalinichenko May 13 '14 at 18:39
  • @crashmstr ugh. I wonder if I can get a non-forward conforming compiler from about 2002 that actually works instead of the gorp in the language definitions these days. (I sure hope MS changes the CLI operator to something else... boy that's gonna hurt compatibility though). –  May 13 '14 at 18:40
  • @MM. I don't think it deserved it, but it's probably because it looks like you're trying to do something stupid. Which you would be, if it wasn't all for sound academic purposes. :) – dlf May 13 '14 at 18:43
  • @ebyrob This is part of the C++ standard, and has nothing to do with C++/CLI. Also, `NULL` is still "valid". – crashmstr May 13 '14 at 18:43
  • Ok; leading answer shows my earlier comment was wrong; there is no "of course" to the idea that `(void*)0` will == 0. – dlf May 13 '14 at 18:47
  • @crashmstr I only bring up C++/CLI because they were using the `nullptr` operator first. (ie: about 2005) –  May 13 '14 at 18:49
  • @dasblinkenlight :: nothing is convertible to `nullptr_t`... – Massa May 13 '14 at 19:48

3 Answers3

11

From C++11 5.2.10/5 Reinterpret cast [expr.reinterpret.cast] (emphasis added):

A value of integral type or enumeration type can be explicitly converted to a pointer. A pointer converted to an integer of suffcient size (if any such exists on the implementation) and back to the same pointer type will have its original value; mappings between pointers and integers are otherwise implementation-defined.

A related bit from 5.2.10/4:

A value of type std::nullptr_t can be converted to an integral type; the conversion has the same meaning and validity as a conversion of (void*)0 to the integral type. [ Note: A reinterpret_cast cannot be used to convert a value of any type to the type std::nullptr_t. —end note ]

Michael Burr
  • 333,147
  • 50
  • 533
  • 760
2

Let's try to answer your question:

It is possible that reinterpret_cast<void*>(x) != nullptr if int x = 0. But it is not mandated. Actually, reinterpret_cast<void*>(x) == nullptr in most platforms but depending on either one is Undefined Behaviour.

Massa
  • 8,647
  • 2
  • 25
  • 26
2

The ISO/IEC 14882:2011 §4.10/1 (and §4.11/1 for member pointers) only says that a _constant integer expression that integral constant expression prvalue of integer type that evaluates to zero is a null pointer constant.

For integer values, the only requirement is in §5.2.10/5, which says that:

A pointer converted to an integer of sufficient size (if any such exists on the implementation) and back to the same pointer type will have its original value; mappings between pointers and integers are otherwise implementation-defined.

So it is also implementation defined whether integer value 0 converts to null pointer or not. In most implementations it does, because it is easier that way.

Jan Hudec
  • 73,652
  • 13
  • 125
  • 172
  • Copy and paste error in the first sentence? "a constant integer expression that integral constant expression" doesn't look right. – nobody May 17 '14 at 01:40