Re: NULL vs 0 vs 0L bikeshed time

From: Erik Trulsson <ertr1013_at_student.uu.se>
Date: Mon, 1 Mar 2004 15:21:45 +0100
On Mon, Mar 01, 2004 at 08:15:57AM -0500, Thomas David Rivers wrote:
> > 
> > 1) Please restrain the need to bikeshed this one to death. I am
> >    sympathetic to technical arguments, but compulsive noise over
> >    such issues is annoying.
> > 
> > 2) Please separate style disussion from technical discussion.
> > 
> > I'd like to commit the following patch. It makes sure that for C
> > and the kernel, NULL is a ((void *)0), and for C++, NULL is either
> > (0L) or 0, with __LP64__ used to define the difference.
> > 
> > The intent is to catch use of NULL where 0 or (0L) should be used.
> > It generates extra warnings (I promise to fix these).
> > 
> 
>  I believe that _may_ be backwards; the C and C++ standards
>  speak to this, and both of them have slightly different
>  requirements.
> 
>  The C standard discuss the NULL constant, implying it is simply
>  a zero (not necessarily cast to a pointer.)
> 
>  But - I believe (and I need to check on this) that the C++
>  standard requires the NULL constant to be a pointer type (so
>  various conversions work.)

It's the other way around.  In C NULL may be defined as an integer
constant with value 0, or such a constant cast to (void*).
In C++ it must be an integer constant. (The reason is that C++ has
stricter type-checking and does *not* perform the implict conversions
between void-pointers and other pointers that C does.)

The patch seems to be technically correct and standards-compliant, and
no correct programs should have any problems with the patch.

However even as it will expose bugs in some programs, the patch will
hide bugs in other programs.

Such buggy programs caused a long thread earlier on how NULL should be
defined which I suspect influenced the creation of this patch.

The problem is that when using an unadorned NULL as an argument to a
vararg function (or a non-prototyped function) there will be no
automatic casting to the correct type.  This means that if NULL is
defined as 0, it will be passed as an integer even if the called
function expects a (void*). For this reason correct programs must
always cast a NULL to the correct type for such functions.
(For functions with a prototype in scope, the argument will be
automatically cast to the correct type.)
This will cause problems if you have 64-bit pointers and 32-bit int's.
This patch will make such programs work as intended and thus hide that
this bug exists, thereby making it less likely that such programs are
actually fixed.


However, as indicated above, the patch will help flush out other bugs
and as such it might be a good idea to use it.


>From a stylistic point of view I think it is really ugly to have NULL
defined in defined in different ways depending on
language/architecture, but I guess that is a necessary evil if one is
to find as many bugs as possible.

On a related note, is there some particular reason for having the C++
definition depend on __LP64__ or could one not just as well define NULL
as (0L) all the time there?
(I.e. is there any platform FreeBSD runs on that have 32-bit longs and
64-bit pointers, or does all of them have pointers and long being the
same size?)

-- 
<Insert your favourite quote here.>
Erik Trulsson
ertr1013_at_student.uu.se
Received on Mon Mar 01 2004 - 05:21:50 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:37:45 UTC