Subject: Re: NULL return value checking
To: Gary Thorpe <gat7634@hotmail.com>
From: Andy Isaacson <adi@hexapodia.org>
List: tech-kern
Date: 04/23/2002 18:36:21
This doesn't belong on tech-kern, but...

On Tue, Apr 23, 2002 at 06:44:20PM -0400, Gary Thorpe wrote:
> As far as I know, using NULL explicitly makes programs more portable (a low 
> priority for code specific to any OS kernel obviously).

False.  Replacing every occurrence of "if(p == NULL)" with "if(p)" or
"if(p == 0)" or even "if(p == '\0')" (ewww!) [1] has precisely zero impact
on the portability of the code.

The place where the difference between NULL and 0 might have
significance is as an argument to a function whose signature is not
known to the compiler (varargs, or a function for which a prototype is
not in scope), and when doing memset() of memory which might include a
pointer. [2]

> I have always seen NULL defined as 0. However, NULL simply represents an 
> invalid value for a pointer, and its actually value is PLATFORM SPECIFIC as 
> far as ANSI compliant code goes. That is, a platform can define NULL to be 
> any value which the platform would interprit to be an invalid pointer.

That may well be, but ISO/IEC 9899:1999 6.3.2.3 (the ISO C99 standard)
requires that

    An integer constant expression with the value 0, or such an
    expression cast to type >void *<, is called a *null pointer
    constant* (55).  If a null pointer constant is converted to a
    pointer type, the resulting pointer, called a *null pointer*, is
    guaranteed to compare unequal to a pointer to any object or
    function.
[...]
    Any two null pointers shall compare equal.

    55)  The macro NULL is defined in <stddef.h> (and other headers) as
         a null pointer constant; see 7.17.

[ >bold monospace< and *italic* text so indicated; footnotes eliminated.
  Typo of "as" for "is" in the footnote is in the original.]

> Assuming it is zero is technically incorrect.

Assuming that the bit pattern stored in a pointer storing a "null
pointer" is all-bits-zero is incorrect.  Assuming that "p = 0" sets p to
a null pointer is explicitly sanctioned by the standard.

[1] '\0' is "[a]n integer constant expression with the value 0", thus
    satisfying the requirements to be considered a null pointer constant.

[2] I recall some debate about what types you were actually allowed to
    memset(, 0, ); certainly unsigned char is OK, signed char is
    probably OK, but there exist implementations where an all-bits-zero
    pointer is NOT == NULL.  I believe the AS/400 may be one.  Certainly 
    there are floating point representations where all-bits-zero is not
    a valid FP number.  Search the standard for "trap representation"
    for relevant stuff.

pedantically yours
-andy