According to §6.3.2.3 ¶3 of the C11 standard, a null pointer constant in C can be defined by an implementation as either the integer constant expression 0
or such an expression cast to void *
. In C the null pointer constant is defined by the NULL
macro.
My implementation (GCC 9.4.0) defines NULL
in stddef.h
in the following ways:
#define NULL ((void *)0)
#define NULL 0
Why are both of the above expressions considered semantically equivalent in the context of NULL
? More specifically, why do there exist two ways of expressing the same concept rather than one?
((void *)0)
has stronger typing and could lead to better compiler or static analyser diagnostics. For example since implicit conversions between pointers and plain integers aren't allowed in standard C.
0
is likely allowed for historical reasons, from a pre-standard time when everything in C was pretty much just integers and wild implicit conversions between pointers and integers were allowed, though possibly resulting in undefined behavior.
Ancient K&R 1st edition provides some insight (7.14 the assignment operator):
The compilers currently allow a pointer to be assigned to an integer, an integer to a pointer, and a pointer to a pointer of another type. The assignment is a pure copy operation, with no conversion. This usage is nonportable, and may produce pointers which cause addressing exceptions when used. However, it is guaranteed that assignment of the constant 0 to a pointer will produce a null pointer distinguishable from a pointer to any object.