Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/18/84; site ccivax.UUCP Path: utzoo!linus!philabs!cmcl2!seismo!rochester!ritcv!ccivax!rb From: rb@ccivax.UUCP (rex ballard) Newsgroups: net.lang.c Subject: Re: if (p), where p is a pointer - PLEASE READ Message-ID: <268@ccivax.UUCP> Date: Thu, 19-Sep-85 19:38:17 EDT Article-I.D.: ccivax.268 Posted: Thu Sep 19 19:38:17 1985 Date-Received: Wed, 25-Sep-85 12:21:15 EDT References: <118@mit-hector.UUCP> <2792@sun.uucp> <693@sfmag.UUCP> Organization: CCI Telephony Systems Group, Rochester NY Lines: 89 > An C idiom I see (and write) frequently is > > if (ptr) > > Will this work correctly on a machine where NULL is not 0? Does it really > need to say > > if (ptr != NULL) If you have the K&R book page 97 says: We write NULL instead of zero however, to indicate that this is a special value for a pointer. In general, integers cannot meaningfully be assigned to pointers; zero is a special case. If you have the use the "C referrence manual", section 7.14 states: The compilers currently allow a pointer to be assigned to an integer, an integer to a pointer, and a pointer to a pointer to a pointer of another type. The assignment is a pure copy operation, with no conversion. This usage is nonportable, and may produce pointers which cause addressing exceptions when used. However, it is guarenteed that assignment of the constant 0 to a pointer will produce a null pointer distinguishable from a pointer to any object. In other words, if NULL is defined as anything other than 0, you are going to blow your banana's if you try to compile someone elses code. If you are really insistant, you can even access address location 0 in memory on some machines since many segmented systems like to have the first byte of executable code. The important thing here is that you are not explicitly required to CAST a NULL for fear of loss of significant bits, sign extension, or similar problems associated with cross-type comparisons (like comparing 0126 < '\240') which require explicit casting. A popular convention is to use the "(char *)0" definition. This can get confusing if your source code contains (int *)NULL. Some (the bad ones) versions of lint give interesting results. Always be sure however of the exact definition of the returned pointers such as EOF is not as consistant. I recently experienced a nasty "gotcha" in an interface with two routines each of which returned 'OK' but the problem was: -------------------------- (file 1) #define OK 0 /* actually include's */ foo() { return(OK); } ----------------------------- (file 2) #define OK -1 /* actually include's */ fie() { return(OK); } ----------------------------- (file 3) foobar() { if(!foo()||!fie()) { errmsg("oops"); return; } /* I normally use "indent -bl" but not on mail */ } Of course foo and fie were very frequently used routines used in separate products so there was no way to fix the various users (many of which used "if(~fie())"). The first example is good it you are certain the function returns NULL, otherwise, forget it. By the way, has anybody figured out how to get lint to shut up about the return codes for { ,s,f}printf(). I have yet to see a standard definition of the return code, but lint keeps giving me "value returned but not used". Isn't this just a tramp from doprntf? I've had one version hand back the value of write (and blew away my stack) even though the return code was supposed to return a char* (sprintf), (Seems it didn't like writing a 4k message). This appears to be a good case for using if(sprintf(...)).