NULL question not in FAQ

Steve Summit scs at adam.mit.edu
Thu Mar 28 17:18:34 AEST 1991


In article <1991Mar26.235643.4498 at ux1.cso.uiuc.edu> phil at ux1.cso.uiuc.edu (Phil Howard KA9WGN) writes:
>Given that the compiler is supposed to translate the constant "0" to the
>appropriate value for a NULL pointer on the machine type, how does one
>get a pointer value whose representation happens to be all zeroes, but
>is [not necessarily a] NULL pointer?
>
>For low level code, e.g. drivers and such, where portability and machine
>independence are not issues, it would still be nice to be able to cast
>address values into pointers as desired.

Indeed.  In fact, K&R1 stated that "the mapping function [between
integral types and pointers] is... machine dependent, but is
intended to be unsurprising to those who know the addressing
structure of the machine."  (Section A14.4, p. 210.)  Of course,
in these more modern and civilized times, wanton conversions
between pointers and integers are more strongly discouraged, and
the "intended to be unsurprising" language does not appear in K&R2.

>Some machine types might very
>well have special functionality at address 0x00000000 and uses some other
>form of address for a NULL.

While such machines are certainly possible (and, with time,
perhaps more so) I would hazard to guess that they are rare at
best.  If a machine is intended to be manipulated directly via
absolute addresses, the manufacturer (and compiler architect)
will presumably make it convenient to do so.  In effect, the old
"intended to be unsurprising" language is likely to be observed.

I can think of three general ways to get a pointer that really
points at address zero.  (All are, of course, unportable, but
that's obviously okay here.)

     1.	char *p = (char *)0;

     2. int zero = 0;
	char *p = (char *)zero;

     3.	char *p;
	memset((char *)&p, 0, sizeof(char *));

(Chris and Henry, and others, have already described several
variations on methods 2 and 3.)

Number one is the most obvious (and easiest) technique; there's
nothing "magic" or surprising about it at all.  It simply assumes
that the internal representation of a null pointer really is
address 0.  (This is, after all, a safe assumption for many
machines, frequent exhortations here to the contrary
notwithstanding.)

Number two is a bit safer, because it dodges the source code null
pointer constant rules in favor of run-time int->pointer
conversion rules, which are more likely to behave as intended, as
long as the compiler author happens to have heard or though of
something equivalent to the old K&R1 "intended to be unsurprising"
advice.  (On a machine with nonzero internal null pointers,
number two wouldn't work if the compiler writer tried to be
"helpful" by making runtime int->pointer coercions, for zero
values, mimic compile-time null pointer generation.)

Number three (including analogous tricks using unions) is
probably the safest pure-C approach, but it is somewhat clumsy.

(Number four, not shown here, is to use an auxiliary assembly
language file, as Chris described, which is the very safest
technique.  "If you want assembly language, you know where to
find it.")

I always use technique one, if it works.  (So far, it always
has, for me.)

Falling-all-over-myself-disclaimer:  Obviously, these techniques
are all unportable, shamelessly violating both the information-
hiding intent of source-code null pointer constants, and also
everything comp.lang.c has been trying to teach anybody about
null pointers.  However, since accessing (for instance) a non-
maskable or power-up interrupt vector at location zero is
inherently unportable, it's obviously acceptable if unportable
code is used to do it.  (Phil understands this; I'm just
re-emphasizing the point.)

If you choose one of the simpler (but less safe) techniques for
accessing location 0 (and I wouldn't blame you for doing so),
you'll have to document that decision and be aware of future
compiler releases which might do things differently.

>Can someone summarize this, depending one what the real answers are, and
>include it in the FAQ in the section on NULL?  This might clear up (or
>confuse further) the distinction of NULL.

It's certainly true that broaching this essentially taboo subject
risks further confusion, and the question doesn't come up very
often, but it's worth a (small) mention in the FAQ list.

                                            Steve Summit
                                            scs at adam.mit.edu



More information about the Comp.lang.c mailing list