Should they warn? Sure. Are they required to? No.
A null pointer constant is not necessarily of pointer type; in fact it typically isn't. (Yes, this is as weird as you think it is.)
A null pointer constant is either an constant integer expression with value 0, or such an expression cast to void*
. So an implementation may have:
#define NULL 0
Which, unfortunately, means that it won't report an error on
char c = NULL;
An implementation could also have:
#define NULL ((void*)0)
which would avoid that particular problem -- but not all implementations do so. (A side note: In C++, ((void*)0)
is not a valid null pointer constant.)
There are other tricks compilers can play to detect such logical errors. For example:
enum { __NULL__ };
#define NULL __NULL__
or even:
#define NULL __magic_builtin_null_pointer_constant__
NULL
still expands to an expression of type int
with value zero, but a compiler could potentially detect the use of this particular expression (if it retains that information internally) and issue a warning.
But ultimately it's up to you as a programmer to avoid this particular error. Unfortunately, you can't depend on the compiler to detect it for you.
Another implication of this is that if need to pass a null pointer as an argument to a function with a variable number of parameters, you can't safely pass just NULL
; you have to cast it to the appropriate pointer type. The execl*()
functions are the most common example of this.
The standard defines the term null pointer constant, but it doesn't say that a null pointer constant is an expression with pointer type. The expression 0
is always of type int
-- and it's always a null pointer constant, even when used in a non-pointer context like
int n = 0;
(And it's an octal constant.) The term null pointer constant needs to be understood as a single concept defined by the standard, not as a phrase whose meaning is derived from its constituent words.