I vaguely remember reading about this a couple of years ago, but I can't find any reference on the net.
Can you give me an example where the NULL macro didn't expand to 0?
Edit for clarity: Today it expands to either ((void *)0)
, (0)
, or (0L)
. However, there were architectures long forgotten where this wasn't true, and NULL expanded to a different address. Something like
#ifdef UNIVAC
#define NULL (0xffff)
#endif
I'm looking for an example of such a machine.
Update to address the issues:
I didn't mean this question in the context of current standards, or to upset people with my incorrect terminology. However, my assumptions were confirmed by the accepted answer:
Later models used [blah], evidently as a sop to all the extant poorly-written C code which made incorrect assumptions.
For a discussion about null pointers in the current standard, see this question.
In C compilers, it can expand to '
((void *)0)
' (but does not have to do so). This does not work for C++ compilers.See also the C FAQ which has a whole chapter on null pointers.
The C FAQ has some examples of historical machines with non-0 NULL representations.
From The C FAQ List, question 5.17:
In modern C,
void *pointer = 0;
is meant to initialize "pointer" to not point at anything. It is platform-specific as to whether that is accomplished by setting the bits of "pointer" to all-zero.In the past, this formal meaning of "0" in a pointer context was not established. It was necessary to set the pointer to the actual value that the platform treated as "doesn't point anywhere". As an example, a platform might choose some fixed address that never gets a page mapped to it. In this case, in an old compiler, the platform might have defined
NULL
as:Of course, today, there's no reason not to define it as
((void*)0)
.NULL
macro in C expands to implementation defined null-pointer constant. It can be anything (since it is implementation-defined), but in pointer context the effect is always the same as if it expanded to constant0
.There has never been a time in standard C history when
NULL
expanded to something specifically not0
, unless you consider(void *) 0
as "not 0". But(void *) 0
forNULL
is widely used to this day.In the GNU libio.h file:
Note the conditional compilation on __cplusplus. C++ can't use ((void*) 0) because of its stricter rules about pointer casting; the standard requires NULL to be 0. C allows other definitions of NULL.
There was a time long ago when it was typed as
((void*)0)
or some other machine-specific manner, where that machine didn't use the all-zero bit pattern.Some platforms (certain CDC or Honeywell machines) had a different bit pattern for NULL (ie, not all zeros) although ISO/ANSI fixed that before C90 was ratified, by specifying that
0
was the correct NULL pointer in the source code, regardless of the underlying bit pattern. FromC11 6.3.2.3 Pointers /4
(though, as mentioned, this wording goes all the way back to C90):