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