[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

On the use of 0 or NULL, the discussion continues...

From: Bob Proulx
Subject: On the use of 0 or NULL, the discussion continues...
Date: Tue, 26 Jun 2007 16:35:31 -0600
User-agent: Mutt/1.5.9i

Since this is not about any particular patch to findutils I have moved
the discussion.


Eric Blake-1 wrote:
> But that is bug-prone.
> Consider:
> printf("%p%d", NULL, 1);
> vs.
> printf("%p%d", 0, 1);

You make a compelling argument for that case.  Because gcc is capable
of checking format strings it can use this to detect this case.
However %p has never produced portable results for me and so I would
never use it in that context and also I don't see the value in
printing as a %p either NULL or 0 immediate value and so this is
rather contrived.  Can you produce a more typical case?

The following is more typical.

  void *var1 = 0;
  void *var2 = NULL;
  printf("%p\n", var1);
  printf("%p\n", var2);

In this case neither gcc nor g++ -O -Wall flag any errors or
differences.  Here is another example.

  typedef struct var { int value; } var_t;
  var_t *var1 = 0;
  if (var1) { printf ("%d\n", var1->value); }
  if (var1 != 0) { printf ("%d\n", var1->value); }
  if (var1 != NULL) { printf ("%d\n", var1->value); }

Of these I prefer '(var1 != 0)' but also have used the simple '(var1)'
with its implied '!= 0' often enough too.  But in the uses I normally
see for NULL such as the above it does not provide additional type
checking.  I welcome counter examples.

I am always happy to use NULL when the function argument type requires
it and no prototypes are in scope.  Such as in K&R C without
prototypes the use of setvbuf, strtok, select, others require a
pointer type argument.  But I am always happier to use C with
prototypes in scope.

I don't like casts in source code and even though NULL
hides/obfuscates the type cast in C it annoys me to have the cast
there just the same.

> On a 32-bit platform, it works.  On a 64-bit platform, it fails.

Your example behaves identically for me on my 64-bit and 32-bit
platforms.  But I don't think that is important to this discussion.

> Using NULL consistently prevents bugs like this, because
> unlike 0, the named constant NULL also conveys type
> information.  Yes, 'gcc -Wall' will tell you about this
> particular example, but I find it easier to use a named
> constant than to risk this type of bug.

Regardless, I still prefer it just the same.  It is the C++ programmer
in me showing through.  I will have to work on keeping that part in
check.  :-)

> Another reason to prefer NULL when a pointer is intended
> is due to function overloading in C++, where foo(0) and
> foo(NULL) could invoke different code paths.

C++ is not C and the type rules are quite different there.  In C++
void* cannot be automatically coerced into pointers of different types
therefore NULL cannot be defined as (void*)0.  Typically in C++ NULL
is defined to be 0.  Outside of g++ in other C++ compilers NULL really
is the same as 0.  g++ uses an internal extension __null to provide
for additional type checking but most other compilers do not.

BTW... I don't feel the need to try to convince anyone.  If I did then
we would have to move on to the one true brace style or more
significantly whether the return from malloc() should be cast (the
return of malloc() should never be cast in C) and so forth. :-)


reply via email to

[Prev in Thread] Current Thread [Next in Thread]