This is an old history: it goes back to C.
There is no null
keyword in C. A null pointer constant in C is either:
- an integral constant expression with value 0, like
0
, 0L
, '\0'
(remember that char
is an integral type), (2-4/2)
- such expression cast to
void*
, like (void*)0
, (void*)0L
, (void*)'\0'
, (void*)(2-4/2)
The NULL
macro (not a keyword!) expands to such null pointer constant.
In the first C++ design, only the integral constant expression was allowed as a null pointer constant. Recently std::nullptr_t
was added to C++.
In C++, but not in C, a const
variable of integral type initialized with an integral constant expression is an integral constant expression:
const int c = 3;
int i;
switch(i) {
case c: // valid C++
// but invalid C!
}
So a const char
initialized with the expression '\0'
is a null pointer constant:
int zero() { return 0; }
void foo() {
const char k0 = '\0',
k1 = 1,
c = zero();
int *pi;
pi = k0; // OK (constant expression, value 0)
pi = k1; // error (value 1)
pi = c; // error (not a constant expression)
}
And you think this is not sound language design?
Updated to include relevant parts of C99 standard...
According to §6.6.6...
An integer constant expression shall have integer type and shall only have operands
that are integer constants, enumeration constants, character constants, sizeof
expressions whose results are integer constants, and floating constants that are the
immediate operands of casts. Cast operators in an integer constant expression shall only
convert arithmetic types to integer types, except as part of an operand to the sizeof
operator.
Some clarifications for C++-only programmers:
- C uses the term "constant" for what C++ programmers know as a "literal".
- In C++,
sizeof
is always a compile time constant; but C has variable length arrays, so sizeof
is sometimes not a compile time constant.
Then, we see §6.3.2.3.3 states...
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.
To see just how old this functionality is, see the identical mirrored parts in the C99 standard...
§6.6.6
An integer constant expression shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof
expressions whose results are integer constants, and floating constants that are the immediate operands of casts. Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to the sizeof
operator.
§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. 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.