50

NULL appears to be zero in my GCC test programs, but wikipedia says that NULL is only required to point to unaddressable memory.

Do any compilers make NULL non-zero? I'm curious whether if (ptr == NULL) is better practice than if (!ptr).

Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
willhf
  • 625
  • 5
  • 9

4 Answers4

65

NULL is guaranteed to be zero, perhaps casted to (void *)1.

C99, §6.3.2.3, ¶3

An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.(55) If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.

And note 55 says:

55) The macro NULL is defined in <stddef.h> (and other headers) as a null pointer constant.

Notice that, because of how the rules for null pointers are formulated, the value you use to assign/compare null pointers is guaranteed to be zero, but the bit pattern actually stored inside the pointer can be any other thing (but AFAIK only few very esoteric platforms exploited this fact, and this should not be a problem anyway since to "see" the underlying bit pattern you should go into UB-land anyway).


So, as far as the standard is concerned, the two forms are equivalent (!ptr is equivalent to ptr==0 due to §6.5.3.3 ¶5, and ptr==0 is equivalent to ptr==NULL); if(!ptr) is also quite idiomatic.

That being said, I usually write explicitly if(ptr==NULL) instead of if(!ptr) to make it extra clear that I'm checking a pointer for nullity instead of some boolean value.


  1. Notice that in C++ the void * cast cannot be present due to the stricter implicit casting rules that would make the usage of such NULL cumbersome (you would have to explicitly convert it to the compared pointer's type every time).
compie
  • 10,135
  • 15
  • 54
  • 78
Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
  • 7
    However, the bytes in a null pointer are not required to be zeros. – aschepler Nov 27 '11 at 19:57
  • 5
    @aschepler: and what did I write in my answer? – Matteo Italia Nov 27 '11 at 19:58
  • 1
    comment was on an older revision. nice answer. – aschepler Nov 27 '11 at 20:05
  • @aschepler: uh yes, I added that bit ~2 minutes after posting the first revision; thank you! :) – Matteo Italia Nov 27 '11 at 20:05
  • great answer, but I think you have a small truth-table slipup: (!ptr) is equivalent to (ptr == 0) rather than (ptr != 0) – willhf Nov 27 '11 at 20:22
  • @willhf: uh correct, sorry, I even edited your question, fixing it.. :S – Matteo Italia Nov 27 '11 at 20:25
  • 1
    Note that `0` is always a null pointer constant, and `NULL` is a null pointer constant, but that doesn't preclude `NULL` from being defined as something other than `0` which the implementation nonetheless treats as a null pointer constant. Regardless, `if (!ptr)` is still equivalent to `if (ptr == NULL)` and must work. (That is, `NULL` is not guaranteed to be zero, but zero is guaranteed to be null). – caf Nov 27 '11 at 21:47
  • @caf: I'm not sure that what you're saying is correct: if the very definition of "null pointer constant" is "an integer constant expression with the value 0" I don't think that `NULL` can be much else... (keeping in mind as always the usual "as if" rule) – Matteo Italia Nov 27 '11 at 22:59
  • @MatteoItalia: I base it on §7.17 which says that `NULL` is an implementation-defined null pointer constant, which I take to mean that a definition like `#define NULL __nullptr` would be allowed as long as the implementation treated it correctly. – caf Nov 27 '11 at 23:07
  • 9
    The most important point to take home: `void *p; memset(&p, 0, sizeof p);` does not make `p` a *NULL* pointer. – Simon Richter Nov 28 '11 at 12:37
  • 3
    @SimonRichter: It doesn't *necessarily* make `p` a null pointer. (It very likely does on most systems, but depending on it makes your code non-portable.) – Keith Thompson Nov 30 '11 at 05:32
11

From the language standard:

6.3.2.3 Pointers
...
3 An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.55) If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.
...
55) The macro NULL is defined in <stddef.h> (and other headers) as a null pointer constant; see 7.17.

Given that language, the macro NULL should evaluate to a zero-valued expression (either an undecorated literal 0, an expression like (void *) 0, or another macro or expression that ultimately evaluates to 0). The expressions ptr == NULL and !ptr should be equivalent. The second form tends to be more idiomatic C code.

Note that the null pointer value doesn't have to be 0. The underlying implementation may use any value it wants to represent a null pointer. As far as your source code is concerned, however, a zero-valued pointer expression represents a null pointer.

Josh Lee
  • 171,072
  • 38
  • 269
  • 275
John Bode
  • 119,563
  • 19
  • 122
  • 198
3

In practice is the same, but NULL is different to zero. Since zero means there's a value and NULL means there isn't any. So, theoretically they are different, NULL having a different meaning and in some cases that difference should be of some use.

ghostbar
  • 161
  • 1
  • 2
  • 10
  • 2
    Close, but not quite accurate. 0 is a value of type int. NULL is a value of pointer type. (Even that's imprecise; `NULL` is a macro that expands to a *null pointer constant*, which yields a *null pointer* when converted to a pointer type.) – Keith Thompson Nov 30 '11 at 15:52
2

in practice no, !ptr is correct

ykhrustalev
  • 604
  • 10
  • 18