About FAQ 5.4

I

I wish

http://www.eskimo.com/~scs/C-faq/q5.4.html

It says "In particular, a cast may still be necessary before NULL

(as before 0) in a function call argument."

Does that mean if I want to pass a NULL to a function,

I should write like this

foo( (char *)NULL ); /* Assume foo receive a pointer to char */
| Modify | Tue, 14 Oct 2003 22:10:40 +0800 (CST)
 
E

Eric Sosman

I said:
http://www.eskimo.com/~scs/C-faq/q5.4.html

It says "In particular, a cast may still be necessary before NULL

(as before 0) in a function call argument."

Does that mean if I want to pass a NULL to a function,

I should write like this

foo( (char *)NULL ); /* Assume foo receive a pointer to char */

There are essentially two cases: One where the compiler
already knows what kind of pointer foo() expects, and one
where it does not know. The latter has two sub-cases:

1. If a prototype for foo() is in scope at the point of
the call, the compiler knows that foo() expects to
receive a `char*' (or a `double*' or `struct x*' or
whatever). In this case, the compiler arranges to
have NULL converted to the desired type automatically;
the cast is unnecessary but harmless.

2a. If there is no prototype for foo() the compiler does
not know what kind of argument is expected. In this
case, the supplied argument is handled according to
the "default argument promotions," which may or may
not produce the correct result. For example, if NULL
is defined as an unadorned `0', the compiler will pass
the argument as an `int' and not as a `char*'. In
this instance, the cast is required.

2b. If a prototype for foo() is in scope but foo() is a
variadic function and the argument in question is one
of the `...' optional arguments, once again the compiler
doesn't know what kind of argument is expected. For the
fixed arguments before the `...' the situation is as in
case [1], but the `...' arguments are handled as in [2a]:
the default argument promotions prevail, and you need
an explicit cast to override them.
 
R

Russell Hanneken

I said:
It says "In particular, a cast may still be necessary before NULL (as
before 0) in a function call argument."

Does that mean if I want to pass a NULL to a function, I should write
like this

foo( (char *)NULL ); /* Assume foo receive a pointer to char */

This is addressed in question 5.2:

http://www.eskimo.com/~scs/C-faq/q5.2.html

The gist of it is you have to use a cast only when a) there is no function
prototype in scope, or b) the argument is part of a variable-length argument
list.

Note that the author (Steve Summit) recommends you cast NULL whenever you
pass it to a function. He lists a few reasons for saying that. I see his
point, but I don't think I'd want to adopt that practice for my own code.
In my opinion, unnecessary casts should be avoided, because they decrease
the legibility of your code, and could hide programming mistakes.
 
D

Dan Pop

http://www.eskimo.com/~scs/C-faq/q5.4.html

It says "In particular, a cast may still be necessary before NULL
(as before 0) in a function call argument."

Does that mean if I want to pass a NULL to a function,
I should write like this

foo( (char *)NULL ); /* Assume foo receive a pointer to char */

ONLY if you don't have a prototype for foo() in scope. Since there is no
good reason for not properly declaring the functions you're using, the
only real case when you have to use the cast is when calling variadic
functions: the compiler has no information about the expected type, so it
cannot perform the conversion itself.

Typical example:

#include <stdio.h>
....
printf("%p\n", (void *)NULL);

OTOH,

fflush(NULL);

is just fine, because the compiler has the prototype of fflush() in scope
and it can perform the conversion itself.

Dan
 
R

Richard Bos

http://www.eskimo.com/~scs/C-faq/q5.4.html

It says "In particular, a cast may still be necessary before NULL
(as before 0) in a function call argument."

Does that mean if I want to pass a NULL to a function,
I should write like this

foo( (char *)NULL ); /* Assume foo receive a pointer to char */

Well, that's debatable.

If you have a decent prototype[1] in scope, and that prototype tells you
that the function is not for a variadic function (or that the pointer is
one of the fixed arguments to a variadic function, not part of the
variable arguments), then no, you don't need to.
If you don't have a prototype in scope, you need to, because then the
compiler can't figure out what type of pointer to convert the null
pointer constant to - it doesn't know what type is required unless the
prototype tells it.
If you the null pointer is one of the variable arguments to a variadic
function, you also need to cast, because the compiler can't figure out
what type of pointer is needed - it can in the fixed arguments, of
course, but there's surprisingly little type information in "...".

The above is all clear and not really debatable. The debate starts when
you ask whether, even though you usually don't _need_ to cast a null
pointer argument, you _should_ do so for stylistic reasons.
On one side of the argument, if you simply cast all null pointer
arguments, you don't need to think about it, and you won't forget to
cast one you must cast.
On the other side, you need to know about the difference between
variadic functions and normal ones anyway, and you shouldn't (and in
C99, can't) call functions without a proper declaration in the first
place; and any superfluous cast is a hinder to the legibility of your
code.
Me, I favour the second side, and only use properly prototyped functions
whenever I can help it, and cast only null pointer constants passed as
variadic arguments. But I don't pretend this is an immutable rule -
unless you're me.

Richard

[1] Or complete old-style definition, I presume; but just don't use
old-style definitions, it's safer. An old-style _declaration_ is not
good enough, in any case. (And the reason I say "I presume" is that
I'm not sure; and don't care to find out, because old-style
definitions are a Bad Thing anyway.)
 
I

Irrwahn Grausewitz

http://www.eskimo.com/~scs/C-faq/q5.4.html

It says "In particular, a cast may still be necessary before NULL

(as before 0) in a function call argument."

Does that mean if I want to pass a NULL to a function,

I should write like this

foo( (char *)NULL ); /* Assume foo receive a pointer to char */

Only if there is no prototype for foo in scope or foo is a variadic
function[1], compare FAQ q5.2, as q5.4 suggests: "The table under
question 5.2 above applies for NULL as well as 0 (an unadorned NULL is
equivalent to an unadorned 0)."

[1] Example: you have to explicitly cast a pointer argument to void* for
evaluation using the "%p" printf format specifier.
| Modify | Tue, 14 Oct 2003 22:10:40 +0800 (CST)

Please drop this escape sequence nonsense, or at least put it after a
valid signature delimiter. Thank you.

Regards
 
J

Joona I Palaste

Irrwahn Grausewitz said:
| Modify | Tue, 14 Oct 2003 22:10:40 +0800 (CST)
Please drop this escape sequence nonsense, or at least put it after a
valid signature delimiter. Thank you.

No. Please just drop the escape sequence crap. This is Usenet, not a
BBS. You can't count on everyone having an MS-DOS relic in their
newsreader.
 
W

William Ahern

I wish said:
http://www.eskimo.com/~scs/C-faq/q5.4.html

It says "In particular, a cast may still be necessary before NULL

(as before 0) in a function call argument."

Does that mean if I want to pass a NULL to a function,

I should write like this

foo( (char *)NULL ); /* Assume foo receive a pointer to char */

As others have said, if there is no way for the compiler to know the
intended type (e.g. no prototype, or varargs), then the default promotions
are used which can have undesirable consequences. I was bitten by this not
too long ago, believe it or not (using the comma operator, though). Read
this thread for a real world scenario:

http://groups.google.com/groups?th=c18bfdde21e11e83

The short story is that Linux (or glibc) does:

#define NULL (void *)0

whereas *BSD does:

#define NULL 0
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top