Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: utzoo!mnetor!uunet!seismo!husc6!hao!noao!arizona!gmt
From: gmt@arizona.edu (Gregg Townsend)
Newsgroups: comp.lang.c
Subject: What is NULL?  There is no right answer!
Message-ID: <1810@megaron.arizona.edu>
Date: Mon, 13-Jul-87 14:08:42 EDT
Article-I.D.: megaron.1810
Posted: Mon Jul 13 14:08:42 1987
Date-Received: Wed, 15-Jul-87 02:05:32 EDT
Organization: U of Arizona CS Dept, Tucson
Lines: 62
Keywords: NULL 0 pointer C


Confusion about the *concept* of NULL seems to be causing most of the problems.
Some credible definitions are:

    1.  NULL is simply shorthand for 0 and is used only for readability.

    2.  NULL is a zero pointer of type (char *), and as such NULL is a legal
        parameter to a function expecting a (char *) argument.

    3.  NULL is a zero pointer of the universal pointer type used by malloc()
        etc., which just happens to be (char *).

I can't find any historical definition that I consider authoritative.  Kernighan
& Ritchie use a privately defined NULL on page 97 but it's not clear that we
should consider that any more universal than ALLOCSIZE defined the line below.
The index entry for NULL also points to a page containing a discussion of 0 as
a pointer value, and using the lower-case adjective "null", but that's pretty
tenuous to be considered a definition.

The value of NULL that most of us use comes from .  The v7 man page
for stdio(3S) defines stdin, stdout, and stderr (which are FILE *) and then
says "A constant `pointer' NULL (0) designates no stream at all."   This sounds
like a narrow definition as a (FILE *), but then the man pages for gets() and
others reference NULL in a (char *) context.

In newer references, Kernighan and Pike (p.177) say NULL is "usually" defined
as (char *)0, while talking about the return from (FILE *) fopen().  Harbison
and Steele (p.94) say it's usually defined as 0.

In the absence of a clear and visible definition, it's no wonder people have
built up concepts based on observed usage.  With many (most?) C compilers,
programs assuming ANY of the above concepts run just fine with NULL defined as
0 in .  With 16-bit ints and 32-bit longs and pointers, a definition
of 0L keeps all the concepts viable.  But when pointers get bigger than longs,
or different pointers have different sizes, a definition satisfying all
assumptions becomes difficult or impossible.

After writing the above paragraphs without prejudice I planned to look at the
proposed ANSI standard [Oct 86].  After all, they've presumably spent a lot
more time wrestling with this problem than most of us.  And now what do I find? 

    (p. 85)  NULL [...] expands to an implementation-defined 
             null pointer constant;

    (p. 30)  An integral constant expression with the value 0, or such an
             expression cast to type void *, is called a null pointer constant.

So allowing for the new form of a universal pointer, they've allowed both #1 and
#3, implementation dependent.  Because (void *) 0 can be compared to any other
pointer without error, if you code assuming definition 1 you're always safe.
The rationale (Sep 86, p. 65) adds:
        [definition of NULL as (void *)0] is necessary on architectures where
        the pointer size(s) do(es) not equal the size of any integer type.
This seems to imply that NULL must always work as an argument to a (void *)
parameter (concept #3), but the rationale isn't the standard.

No wonder everyone's confused.  I learned something just researching this
message.  There is no authoritative, correct answer.  Even the proposed 
new standard is ambivalent.

     Gregg Townsend / Computer Science Dept / Univ of Arizona / Tucson, AZ 85721
     +1 602 621 4325      gmt@Arizona.EDU       110 57 17 W / 32 13 47 N / +758m