[comp.lang.c] Is "if

greyham@hades.OZ (Greyham Stoney) (04/11/90)

When using functions that return pointers, it's pretty common to return a
NULL pointer when something fails. What is the simplest portable method
that can be used to detect the NULL pointer being returned?.

For example you can compare it with NULL:
	char *buffer;

	if ((buffer = malloc(50)) != NULL)
		use(buffer);
	else
		exit(1);

But can you also just do an aritmetic check on the cast value of the pointer?:
	char *buffer;

	if (buffer = malloc(50))	/* yes, that SHOULD be =, not == */
		use(buffer);
	else
		exit(1);

Now that second one looks much simpler to me, but is it as portable?. Now
you might say "Ah, but the value of NULL is not necessarily zero!". But a
NULL pointer is a special case - K&R says that casting anything with a
value 0 to a pointer yeilds a NULL pointer; so presumably casting a NULL
pointer back to value yeilds a zero. The actual value of the NULL pointer is
irrelevant since the implicit cast will convert to and from it.

Is this correct?. Can I just do:
	if (buffer) free(buffer)
And stuff like that?.
							Greyham.
-- 
/*  Greyham Stoney:                            Australia: (02) 428 6476  *
 *     greyham@hades.oz  - Ausonics Pty Ltd, Lane Cove, Sydney, Oz.      *
 *          "BUT THAT'S JUST A BUTTON ON A STRING, BASICLY!!!"           */

diamond@tkou02.enet.dec.com (diamond@tkovoa) (04/11/90)

In article <656@hades.OZ> greyham@hades.OZ (Greyham Stoney) writes:

>	if ((buffer = malloc(50)) != NULL)
>But can you also just do an aritmetic check on the cast value of the pointer?:
>	if (buffer = malloc(50))	/* yes, that SHOULD be =, not == */

Yes it is portable, just not readable.  They both have the same effect,
and should generate identical code.  But you notice that the second one
is longer, because you have to include that comment in order to make it
almost as readable as the first one.

>	if (buffer) free(buffer)

This is also portable, and almost readable.  Again, to be really readable,
you should still compare to NULL, but I grant that it would make your
source code longer this time.

-- 
Norman Diamond, Nihon DEC     diamond@tkou02.enet.dec.com
This_blank_intentionally_left_underlined________________________________________

dolf@idca.tds.PHILIPS.nl (Dolf Grunbauer) (04/11/90)

In article <1461@tkou02.enet.dec.com> diamond@tkou02.enet.dec.com (diamond@tkovoa) writes:
<In article <656@hades.OZ> greyham@hades.OZ (Greyham Stoney) writes:
<
<>	if (buffer) free(buffer)
<
<This is also portable, and almost readable.  Again, to be really readable,
<you should still compare to NULL, but I grant that it would make your
<source code longer this time.

How about just a:
	free(buffer)

The manual pages I know allow a NULL pointer and doing nothing in this case.
Is this generally true ?
-- 
Dolf Grunbauer          Tel: +31 55 433233  Internet dolf@idca.tds.philips.nl
Philips Telecommunication and Data Systems  UUCP ....!mcsun!philapd!dolf
Dept. SSP, P.O. Box 245, 7300 AE Apeldoorn, The Netherlands         n   n   n
It's a pity my .signature is too small to show you my solution of  a + b = c

tjr@cbnewsc.ATT.COM (thomas.j.roberts) (04/11/90)

From article <1461@tkou02.enet.dec.com>, by diamond@tkou02.enet.dec.com (diamond@tkovoa):
> In article <656@hades.OZ> greyham@hades.OZ (Greyham Stoney) writes:
>>	if (buffer = malloc(50))	/* yes, that SHOULD be =, not == */
> 
> Yes it is portable, just not readable...

But beware. In modern compilers (e.g. TURBO C), this will generate
a warning (HURRAY!) about a questionable assignment in a conditional context.

Avoid the warning with either:
	if( (buffer=malloc(50)) != 0) [...]
or
	if( !!(buffer=malloc(50)) ) [...]

Personally, I either invert the if:
	buffer = malloc(50);
	if(!buffer) goto error;		/* Yes, it is usually a goto, for there
					   are often dozens of error legs */
Or, more often, supply my own error-checking routine to malloc:
	extern void *emalloc(size_t n_bytes);
	buffer = emalloc(50);	/* emalloc() bombs on malloc() failure */

Tom Roberts
att!ihlpl!tjrob

henry@utzoo.uucp (Henry Spencer) (04/11/90)

In article <717@ssp11.idca.tds.philips.nl> dolf@idca.tds.PHILIPS.nl (Dolf Grunbauer) writes:
>How about just a:
>	free(buffer)
>
>The manual pages I know allow a NULL pointer and doing nothing in this case.
>Is this generally true ?

Unfortunately, no.  Old implementations of free() explode when given NULL.
-- 
With features like this,      |     Henry Spencer at U of Toronto Zoology
who needs bugs?               | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

karl@haddock.ima.isc.com (Karl Heuer) (04/11/90)

In article <656@hades.OZ> greyham@hades.OZ (Greyham Stoney) writes:
>But can you also just do an aritmetic check on the cast value of the pointer?:

No.

>K&R says that casting anything with a value 0 to a pointer yeilds a NULL
>pointer; so presumably casting a NULL pointer back to value yeilds a zero.

Not necessarily.

>	if (buffer = malloc(50))	/* yes, that SHOULD be =, not == */
>	if (buffer) free(buffer)

But these are acceptable (if you like that style, which I don't).  You seem to
believe that `if (buffer)' means `if ((int)buffer != 0)' (which would not be
a valid test), but in fact it means `if (buffer != (char *)0)' (which is quite
correct).

Karl W. Z. Heuer (karl@ima.ima.isc.com or harvard!ima!karl), The Walking Lint

karl@haddock.ima.isc.com (Karl Heuer) (04/11/90)

In article <717@ssp11.idca.tds.philips.nl> dolf@idca.tds.PHILIPS.nl (Dolf Grunbauer) writes:
>How about [skipping the test for NULL and writing just]
>	free(buffer)
>The manual pages I know allow a NULL pointer and doing nothing in this case.
>Is this generally true ?

It's a new feature of the ANSI C library.  It should be avoided if you need
to retain portability to old implementations.

Karl W. Z. Heuer (karl@ima.ima.isc.com or harvard!ima!karl), The Walking Lint

henry@utzoo.uucp (Henry Spencer) (04/12/90)

In article <656@hades.OZ> greyham@hades.OZ (Greyham Stoney) writes:
>...What is the simplest portable method
>that can be used to detect the NULL pointer being returned?.
>
>	if ((buffer = malloc(50)) != NULL)
>	if (buffer = malloc(50))	/* yes, that SHOULD be =, not == */

The two are precisely synonymous.  Use of a C expression in a conditional
context always gives an implicit comparison to zero, and comparison of a
pointer to the constant zero (e.g. to NULL, properly defined to be 0) is
comparison to a null pointer.  Any compiler which produces different
code for the two is broken or very stupid.

However, the first one is a whole lot easier to read, and is less work to
type if you include the comment on the second one (which is NOT optional!).

>NULL pointer is a special case - K&R says that casting anything with a
>value 0 to a pointer yeilds a NULL pointer; so presumably casting a NULL
>pointer back to value yeilds a zero...

No.  K&R says that casting a *constant* value 0 to a pointer yields a
null pointer.  This does not generalize any further.
-- 
With features like this,      |     Henry Spencer at U of Toronto Zoology
who needs bugs?               | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

scjones@sdrc.UUCP (Larry Jones) (04/12/90)

In article <656@hades.OZ>, greyham@hades.OZ (Greyham Stoney) writes:
> Is this correct?. Can I just do:
> 	if (buffer) free(buffer)
> And stuff like that?.

Yes.  A null pointer is guaranteed to compare equal to zero, so
if (ptr) and if (!ptr) are completely portable.  Many will debate
whether they are stylistically good or bad, but they definitely
are portable.
----
Larry Jones                         UUCP: uunet!sdrc!scjones
SDRC                                      scjones@SDRC.UU.NET
2000 Eastman Dr.                    BIX:  ltl
Milford, OH  45150-2789             AT&T: (513) 576-2070
"You know how Einstein got bad grades as a kid?  Well MINE are even WORSE!"
-Calvin

darcy@druid.uucp (D'Arcy J.M. Cain) (04/14/90)

In article <1461@tkou02.enet.dec.com> diamond@tkou02.enet.dec.com (diamond@tkovoa) writes:
>In article <656@hades.OZ> greyham@hades.OZ (Greyham Stoney) writes:
> [...]
>>	if (buffer) free(buffer)
>
>This is also portable, and almost readable.  Again, to be really readable,
>you should still compare to NULL, but I grant that it would make your
>source code longer this time.
>
I know that NULL == 0 but I can't help feeling nervous about it.  I always
use something like "if (buffer == NULL)" and assume that the optimiser will
do the right thing.  Am I too paranoid or is this good defensive programming?


-- 
D'Arcy J.M. Cain (darcy@druid)     |   Government:
D'Arcy Cain Consulting             |   Organized crime with an attitude
West Hill, Ontario, Canada         |
(416) 281-6094                     |

henry@utzoo.uucp (Henry Spencer) (05/02/90)

In article <7180@ncar.ucar.edu> steve@groucho.ucar.edu (Steve Emmerson) writes:
>Doesn't the standard guarantee that there exists an implementation-
>dependent integral type capacious enough to handle the pointer-to-
>integer-to-pointer conversion sequence and return the original pointer?

No.  Indeed, the only reason why you can define NULL to be `(void *)0'
instead of just `0' or `0L' is the possibility that there may not be
an integer type large enough to match the size of a pointer.  (This does
not matter to legal programs, but on many machines you can increase the
odds that a badly-written illegal program will accidentally work if you
make NULL the same size as most pointers.)

>If so, then "unsigned long" would appear to be a safe bet -- there being
>nothing longer.

Does not follow.  An implementation might provide longer types.
-- 
If OSI is the answer, what is |     Henry Spencer at U of Toronto Zoology
the question?? -Rolf Nordhagen| uunet!attcan!utzoo!henry henry@zoo.toronto.edu