I have not seen a compiler that did not have the NULL value set to
zero (Not confusing nul and NULL) or a cast as a pointer.
My understanding of NULL is that it is pointer value that will never
be in the addressing range of your program. The NULL value is up to
the compiler (and may be dictated by the hardware). There is no
guarantee that NULL will be a cast of any particular value.
Other C compilers could use 0xffffffff as NULL rather than 0. Using a
numeric value could break code on other compilers.
You're mixing up two or maybe three different things: The run-
time value of a null pointer, the representation of that value as
a batch of bytes, and the source-code construct that produces it.
In an attempt to dispel some confusion:
- `NULL' is an identifier, a source-code construct. Various
Standard headers define the name as a macro, also a source-
code construct.
- The `NULL' macro defined by the Standard headers expands to
a "null pointer constant," which is "an integer constant
expression with the value 0, or such an expression cast to
type void *". Expressions, constant expressions, and casts
are also source-code constructs.
- (Why do I keep harping on "source-code construct?" Because of
the confusion between the way a value is "spelled" in source
code and the way that value "actually looks" at run-time. When
you write '\n' in source, do you imagine that the corresponding
run-time value involves two quote marks, a back-slash, and an n?
Just so with 0 or (void*)0: They are the source code's way of
denoting a value, not images of the value.
- Onward: When they appear in pointer contexts, 0 and (void*)0
create null pointer values in the run-time program (but see
below). These values have unspecified bit patterns (plural
intended), at the implementation's whim. Many implementations
use all-bits-zero-for-however-many-bytes-it-requires as a null
pointer value, but this is not obligatory; the FAQ mentions
some systems that use(d) other representations.
- Even when a null pointer constant appears in the source code,
it is not guaranteed that a null pointer value appears in the
run-time program. For example, `if (p == NULL) return;' might
produce code like `ld r0,p; tst r0; jz return_point;' -- and
where in this code is there a bit pattern representing a null
pointer value?
- Finally, to the null pointer value itself. No matter how it
is represented in the machine, we know (1) all null pointer
values compare equal to each other, and (2) all null pointer
values compare *un*equal to pointers to any variable or function
or allocated memory area. We need not (and should not) appeal
to notions of an "addressing range" to explain how this is made
to work; as C programmers all we need to know (and all we should
rely on) is that it *does* work, somehow. An implementor, of
course, has the burden of making it work and thus must care about
the chosen mechanisms, just as he must care about how `static'
variables get their initial values. As programmers, we should
fret about the former only as much as we do about the latter.
If this seems pedantic, that's only because it *is* pedantic.
But there's so much confusion about null pointers -- the FAQ devotes
an entire section to the topic -- that perhaps a small helping of
pedantry is called for.