26

I need to be able to differentiate between NULL and 0 in c++.

Is there a way to use something like the === operator (such as the identity operator found in JavaScript) to tell the difference between NULL and 0 in c++?

Blitzkoder
  • 1,768
  • 3
  • 15
  • 30
adam
  • 463
  • 1
  • 7
  • 15
  • 7
    Can you give an example of how you might perform this comparison in the first place? `int*` and `int` are two entirely different things. You'd have to cast in order to get these to compare, which means you're going out of your way to make this comparison ambiguous. – tadman May 10 '13 at 18:28
  • 5
    C++ doesn't work like that. It sounds like you're thoroughly misusing pointers. – SLaks May 10 '13 at 18:29
  • 31
    Use `nullptr` instead of `NULL`, problem solved. – Blastfurnace May 10 '13 at 18:30
  • 3
    A reference to expand on my previous comment: [What exactly is nullptr?](http://stackoverflow.com/questions/1282295/what-exactly-is-nullptr) – Blastfurnace May 10 '13 at 18:34
  • 6
    It is not possible to "differentiate between `NULL` and `0`" in C++ simply becuase in general case they are exactly the same. If you are talking about something else, you have to provide more deatils about what you are trying to do. – AnT stands with Russia May 10 '13 at 19:09
  • To clarify: if `NULL` isn't exactly `0`, then it differs only in type. Eg. `NULL` might be `0L`. `int(NULL)` definitely is the same as `0`. – MSalters May 10 '13 at 22:42
  • 2
    A lot of the answer seem to be assuming that what the OP means by `NULL`, is what c++ means by that token. It's not clear to be that this is the case, in which case the best answer would be to explain the difference between that in [whatever language uses `NULL` the way the OP means] and in c++. – dmckee --- ex-moderator kitten May 11 '13 at 01:25

7 Answers7

40

NULL is a preprocessor macro, and will be replaced directly with 0 when the preprocessor runs. So in short, no.

RandyGaul
  • 1,915
  • 14
  • 21
36

Such operator is not necessary in C++, because there is no built-in type that would be capable of storing both these values in a meaningfully distinguishable way. Moreover, NULL is not required in C++, because you can replace it with zero 0 everywhere a NULL goes. Bjarne Stroustrup even suggests avoiding NULL altogether:

In C++, the definition of NULL is 0, so there is only an aesthetic difference. I prefer to avoid macros, so I use 0. Another problem with NULL is that people sometimes mistakenly believe that it is different from 0 and/or not an integer. In pre-standard code, NULL was/is sometimes defined to something unsuitable and therefore had/has to be avoided. That's less common these days.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 2
    +1 This is the heart of the issue. In C++ you answer this question with a typecheck. – Ben Voigt May 10 '13 at 18:32
  • Well, there are a lot of types which can store both `NULL` and `0`: all integral types. `NULL` simply **is** `0`. There is of course no type which can store both 0 and a null pointer, but that's a different story. – Angew is no longer proud of SO May 10 '13 at 18:34
  • @Angew That would be the same value, though. In other languages, such as Javascript where `===` originates, zero is an object and NULL is not. In C++ both NULL and zero are indistinguishable. – Sergey Kalinichenko May 10 '13 at 18:36
  • 1
    @Angew: I think you're missing the underlying request in this question. Even if the question says 'NULL', it means "null pointer". – Ben Voigt May 10 '13 at 18:38
  • 1
    @BenVoigt Then the question would be meaningless, you can't compare pointers and integers, so it's trivial to tell them apart. My comment was just referring to the wording in the answer, edited since then. – Angew is no longer proud of SO May 10 '13 at 18:41
  • 1
    @dasblinkenlight, it might be worth showing examples with (non-builtin) types that do allow storing both (numeric 0) and (null pointer). For example Win32 VARIANT (check whether `vt == VT_EMPTY` or `vt == VT_NULL`) and `boost::variant` and `boost::optional`. – Ben Voigt May 10 '13 at 18:41
  • Also, the built-in `float` and `double` types have a meaningful distinction between 0.0 and NaN. – dan04 May 11 '13 at 15:06
16

There is no difference -- NULL is required to be defined as an integer constant with the value 0. The integer type is typically chosen to be the same size as a pointer, but that's not actually necessary. In C it's frequently defined as (void *)0, but this is not allowed in C++ (in C it's reasonable because a pointer to void supports implicit conversion to any other pointer type--but in C++ that's not allowed, so if NULL were defined as a pointer to void, you'd have to cast it to get any other pointer type).

When/if you want a null pointer that's distinguishable from 0, you probably want to use nullptr. nullptr can be assigned to a variable of any pointer type, but cannot be assigned to an integer type (e.g., int, long, size_t, etc.)

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • 2
    Isn't `NULL` defined as roughly `(void*) 0`? – tadman May 10 '13 at 18:29
  • 4
    @tadman: In C it is, in C++ no. C++ NULL is either `0` or `0u` or `0uL` or `0uLL` -- it specifically is required to have an integral type. – Ben Voigt May 10 '13 at 18:30
  • Your edit makes no sense IMO, as a pointer set with `nullptr` isn't distinguishable from a pointer set with `0`. The essential difference is that `nullptr` has no implicit conversion to any numeric type. – Ben Voigt May 10 '13 at 18:35
  • @BenVoigt: That's the point -- you can't (for example) accidentally assign `nullptr` to an integer. – Jerry Coffin May 10 '13 at 18:40
  • @Jerry: Right, but does a type exist where `T x{nullptr}, y{0};` is valid and gives `x != y`? Probably so, I guess some application of `boost::variant`. – Ben Voigt May 10 '13 at 18:43
  • @BenVoigt: Presumably you meant `T *x{nullptr}, *y{0};`. In such a case, they'll both end up as null pointers, but before the assignment, the two can be distinguished. For example, if you have a function `f` overloaded for `void *` and `int` parameters, `f(NULL)` will invoke the `int` one and `f(nullptr)` will invoke the `void *` one. – Jerry Coffin May 10 '13 at 18:45
  • @Jerry: No, I definitely didn't mean `T*`. You can make `T` be `void*` if you want, but they you won't get `x != y`. My question is whether you can think up any existing type that acts like my last comment said. – Ben Voigt May 10 '13 at 19:03
  • @BenVoigt: My point was, both are really intended to be used as pointers, so the real *intent* would be to get a null pointer either way. If you use a non-pointer type, then overloaded ctors that take int and pointer types could give different results for the two (though it's a little hard to be sure what pre-existing types might do that). – Jerry Coffin May 10 '13 at 19:28
  • 6
    In C, `NULL` can be defined either as an integer constant expression with the value 0 (such as `0`) or as such an expression cast to `void*` (such as `((void*)0)`). Parentheses are added as needed to ensure that it's a primary expression and avoid operator precedence problems. C++ doesn't permit the `((void*)0)` form. – Keith Thompson May 10 '13 at 20:42
  • @KeithThompson: Yes -- but it's only tagged C++, not C. – Jerry Coffin May 10 '13 at 21:22
  • 3
    It should be mentioned that the *reason* C++ doesn't allow `NULL` to be defined as `((void*)0)` is that C++ doesn't allow `void*` to be implicitly converted to other pointer types like in C. – dan04 May 11 '13 at 02:03
10

I think what you're asking is:

If I have a variable x, how can I distinguish between

  1. x contains a numeric 0
  2. x is missing / no value / null pointer

C++ has strongly-typed variables, so it's unusual even to have a variable where both of these are possibilities. But NULL-valued logic is useful in databases, so lets look at a few ways of representing that in C++.

  1. Situation: x == 0 is detected in template code, where the meaning of 0 isn't clear.
    Answer: Use a type trait to find out whether x is a pointer (case #2) or not (case #1).

    if (is_pointer(x))
    
  2. Situation: p is a C-style NULL-valued logic variable, which is pointer to numeric value.
    Answer: Test whether the pointer is null. If not, you can check the pointed-to object.

    if (p == NULL) { /* case 2 */ }
    else if (*p == 0) { /* case 1 */ }
    
  3. Situation: v is a Win32 VARIANT, which is a discriminated union used to implement variables in scripting languages.
    Answer: Check the discriminating key.

    if (v.vt == VT_EMPTY) { /* case 2a */ }
    else if (v.vt == VT_NULL) { /* case 2b */ }
    else if (v.vt == VT_I4 && v.lVal == 0) { /* case 1 */ }
    else if (v.vt == VT_I2 && v.iVal == 0) { /* case 1 */ }
    // and so on
    
  4. Situation: o is a C++-ism representation of NULL-valued logic, such as boost::optional.
    Answer: These C++ classes for NULL-valued logic provide a way to detect missing values. A specific example with boost::optional<int> shows that it's designed to be accessed just like a pointer:

    boost::optional<int> o;
    if (!o) { /* case 2 */ }
    else if (*o == 0) { /* case 1 */ }
    
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • 1
    Good answer, but you haven't mentioned null_ptr. I think it is very powerful replacement for NULL in modern C++. – George Gaál May 10 '13 at 23:34
  • @GeorgeGaál: `nullptr` is completely irrelevant to this question. A null pointer value is a null pointer value, whether the source code used `0` or `nullptr`. – Ben Voigt May 11 '13 at 03:45
1

In general NULL and 0 are the same thing in C++ (both are a null pointer).

I'm going to assume you're asking how to get an integral type in C++ which can have both NULL and 0 values, and to be able to tell the difference.

You can do this with boost::optional:

boost::optional<int> val;

if(!val)
    std::cout << "null" << std::endl;
else
    std::cout << "val=" << *val << std::endl;

val = 0;
if(!val)
    std::cout << "null" << std::endl;
else
    std::cout << "val=" << *val << std::endl;

This should print out null and val=0.

Regexident
  • 29,441
  • 10
  • 93
  • 100
Mark B
  • 95,107
  • 10
  • 109
  • 188
1

Actually it depends on what you are comparing NULL or 0 with … if you are comparing a integer then NULL should work as 0 if you are comparing with an address 0 will work as NULL.

Regexident
  • 29,441
  • 10
  • 93
  • 100
sethi
  • 1,869
  • 2
  • 17
  • 27
0

NULL is a preprocessor macro which will be immediately replaced by 0 before compilation starts.

C++ doesn't have Javascript's operator ===. The closest thing that comes to that in C++, that I can think of, is a sort pseudo-equivalence relation, which accomplishes the same thing with JS ===:

if (!(x > y) && !(y > x)) { /* ... */ }

KeyC0de
  • 4,728
  • 8
  • 44
  • 68