PU Relation between null pointer and integer zero in C

May 17, 2017

What C standard says?

§ 6.3.2.3 of the C99 standard says

  • An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.
  • 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.

Explanation

  • First, 0 is a null pointer constant.
  • When is a null pointer constant converted to a pointer type?
    • assignment: int *p = 0;
    • comparison: p == 0 or p or !p
    • dereferencing: *p
    • casting: (void *)0
  • So, it's safe to use 0 to initialize a pointer. (I love it)

Compiler's responsibility

C compilers recognize the value 0 (when used as a pointer) in source code to be a special value that means NULL, which is defined in .

Even when the implementation internally uses some other binary value to mean a null pointer, the compiler translates from 0 in the source code into its internal representation of a null pointer.

  • The underlying architecture doesn't matter.
  • If the underlying architecture has a null pointer value defined as address 0xDEADBEEF, then it is up to the compiler to sort this mess out.
  • As such, even on this funny architecture,
    • the following ways are still valid ways to check for a null pointer:
    • if (!pointer), if (pointer == NULL), if (pointer == 0)

Following are some valid ways to check for a null pointer:

if (pointer == NULL)
  • the macro NULL is provided in the header file stddef.h.
  • NULL is defined to compare equal to a null pointer.
  • It is implementation defining what the actual definition of NULL is, as long as it is a valid null pointer constant.
if (pointer == 0)
  • The integer constant literal 0 has different meanings depending upon the context in which it's used.
  • In all cases, it is still an integer constant with the value 0, it is just described in different ways.
  • If a pointer is being compared to the constant literal 0, then this is a check to see if the pointer is a null pointer.
  • This 0 is then referred to as a null pointer constant.
  • The C standard defines that 0 cast to the type void * is both a null pointer and a null pointer constant.
if (!pointer)
  • This if statement implicitly checks is not 0, so we reverse that to mean is 0.

The following are INVALID ways to check for a null pointer:

int mynull = 0;
...
if (pointer == mynull)
  • To the compiler this is not a check for a null pointer, but an equality check on two variables.
  • This might work if mynull never changes in the code and the compiler optimizations constant fold the 0 into the if statement.
  • But this is not guaranteed and the compiler has to produce at least one diagnostic message (warning or error) according to the C Standard.
// even when the underlying architecture has a null pointer value defined as address `0xDEADBEEF`, following are not valid.
#define MYNULL (void *) 0xDEADBEEF
if (pointer == MYNULL)
if (pointer == 0xDEADBEEF)
  • and 0xDEADBEEF is not 0, so according to C standard, it's not a null pointer constant in any case.
  • as a result, 0xDEADBEEF will never be convert into a null pointer.
  • these are seen by a compiler as normal comparisons.

END