[comp.lang.c] 10 commandments and the NULL pointer?

einari@rhi.hi.is (Einar Indridason) (11/08/90)

I just 'troff'-ed Henry Spencer's 10 commandments and read it.  It is great
and it is now hanging in my wall at home.  However one question entered my
mind:  (a question that perhaps should be in the FAQ list, and perhaps is
there?)

The question is about NULL pointers.  Suppose I have the following code:

------------------------------------------------------
#include <whatever_needs_to_be_included.h>

int do_something(int *par1, double *par2, char *par3)
{
	/* do something with those pointers/parameters */
	/* return some value to tell how well we did */
}


main()
{
	.....

	x = do_something(NULL, NULL, NULL);
	/* is            ^^^^  ^^^^  ^^^^  this right or should I write: */

	x = do_something( (int *)NULL, (double *)NULL, (char *)NULL );

	/* which form should I use?  (that is, should I cast the NULL value */
	/* to int pointer, double pointer, char pointer?) */
}
-----------------------------------------


Thanks for your time.

--
Internet: einari@rhi.hi.is        |   "Just give me my command line and drag
UUCP: ..!mcsun!isgate!rhi!einari  |   the GUIs in the waste basket!!!!"

General Surgeons warning:  Masking the 8th bit can seriously damage your brain!!

hp@vmars.tuwien.ac.at (Peter Holzer) (11/08/90)

einari@rhi.hi.is (Einar Indridason) writes:
>#include <whatever_needs_to_be_included.h>

>int do_something(int *par1, double *par2, char *par3)
>{
>	/* do something with those pointers/parameters */
>	/* return some value to tell how well we did */
>}


>main()
>{
>	.....

>	x = do_something(NULL, NULL, NULL);
>	/* is            ^^^^  ^^^^  ^^^^  this right or should I write: */

>	x = do_something( (int *)NULL, (double *)NULL, (char *)NULL );

>	/* which form should I use?  (that is, should I cast the NULL value */
>	/* to int pointer, double pointer, char pointer?) */
>}
>-----------------------------------------

If you are using ANSI C, then the above form is allright,
because the compiler knows from the prototype above the types of
the pointers and inserts the casts by itself.

If you (or someone else) want to port your program to an old
compiler (and many of them are still in use) and change the
declaration of do_something to:

int do_something (par1, par2, par3)
	int	* par1;
	double	* par2;
	char	* par3;
{
/* ... */
}

you will need the casts because the compiler does not check (much
less convert) any
arguments. 
--
|    _  | Peter J. Holzer                       | Think of it   |
| |_|_) | Technical University Vienna           | as evolution  |
| | |   | Dept. for Real-Time Systems           | in action!    |
| __/   | hp@vmars.tuwien.ac.at                 |     Tony Rand |

jc@atcmp.nl (Jan Christiaan van Winkel) (11/08/90)

From article <2390@krafla.rhi.hi.is>, by einari@rhi.hi.is (Einar Indridason):
# int do_something(int *par1, double *par2, char *par3)
# {
# 	/* do something with those pointers/parameters */
# 	/* return some value to tell how well we did */
# }
# 
# 
# main()
# {
# 	.....
# 
# 	x = do_something(NULL, NULL, NULL);
# 	/* is            ^^^^  ^^^^  ^^^^  this right or should I write: */
# 
# 	x = do_something( (int *)NULL, (double *)NULL, (char *)NULL );
# }
since you used prototypes, you can just as well use
 	x = do_something(0, 0, 0);
because the compiler knows the 0's are used in pointer context; it will
automagically cast the value to the right type. Read the FAQ for more
info on the NULL pointer, there's actually quite a lot to be told about
it.
JC

-- 
___  __  ____________________________________________________________________
   |/  \   Jan Christiaan van Winkel      Tel: +31 80 566880  jc@atcmp.nl
   |       AT Computing   P.O. Box 1428   6501 BK Nijmegen    The Netherlands
__/ \__/ ____________________________________________________________________

chris@mimsy.umd.edu (Chris Torek) (11/09/90)

In article <2390@krafla.rhi.hi.is> einari@rhi.hi.is (Einar Indridason) writes:
>However one question entered my mind:  (a question that perhaps should
>be in the FAQ list, and perhaps is there?)

It is.

>int do_something(int *par1, double *par2, char *par3) ...
>	x = do_something(NULL, NULL, NULL);
>	/* is            ^^^^  ^^^^  ^^^^  this right or should I write: */

You have provided a prototype declaration (via a preceding prototype
definition) in which all three parameters are covered by prototypes.
They are therefore in assignment contexts and as a result, an integer
constant zero or same-cast-to-void (NULL expands to one of these two)
suffices, because the pointer context is supplied by the assignments.

>	x = do_something( (int *)NULL, (double *)NULL, (char *)NULL );
>	/* which form should I use?  (that is, should I cast the NULL value */
>	/* to int pointer, double pointer, char pointer?) */

Some people prefer the latter form even when prototypes are used, as it
helps remind the reader what is going on.  Still others prefer something
like:

	/* special distinguished second parameter to DoSomething */
	#define NOMATRIX ((double *)NULL)
	...
		x = do_something(NOFOO, NOMATRIX, NOBAR);
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 405 2750)
Domain:	chris@cs.umd.edu	Path:	uunet!mimsy!chris

gwyn@smoke.brl.mil (Doug Gwyn) (11/09/90)

In article <2390@krafla.rhi.hi.is> einari@rhi.hi.is (Einar Indridason) writes:
>	x = do_something(NULL, NULL, NULL);
>	/* is            ^^^^  ^^^^  ^^^^  this right or should I write: */
>	x = do_something( (int *)NULL, (double *)NULL, (char *)NULL );

Use the latter.  The former might or might not work, depending on system
details.

gwyn@smoke.brl.mil (Doug Gwyn) (11/09/90)

In article <681@atcmpe.atcmp.nl> jc@atcmp.nl (Jan Christiaan van Winkel) writes:
>since you used prototypes, you can just as well use
> 	x = do_something(0, 0, 0);

Only if there is a prototype declaration of do_something() in scope;
it is better to not rely on such automatic pointer coercion (available
only under ANSI C) and instead just supply the right types.