Xref: utzoo comp.arch:5117 comp.lang.c:10669 Path: utzoo!utgpu!water!watmath!clyde!att!mtunx!pacbell!ames!oliveb!sun!gorodish!guy From: guy@gorodish.Sun.COM (Guy Harris) Newsgroups: comp.arch,comp.lang.c Subject: Re: null pointers (was: negative addresses) Message-ID: <55645@sun.uucp> Date: 8 Jun 88 02:45:32 GMT References: <226@proxftl.UUCP> <3100002@hpmwtla.HP.COM> Sender: news@sun.uucp Followup-To: comp.lang.c Lines: 70 (The preceding article's contents represent a misunderstanding of the C language, rather than a valid statement of what an architecture should or should not have; I've therefore redirected followups to "comp.lang.c", although many readers there are probably tired of seeing these same misunderstandings....) > This presents a sequential search through a linear list more positively than > > #include/*stupid place for NULL*/ > ... > Foobar *foobar; > for (foobar = first; foobar != (Foobar*)NULL; foobar = foobar->next) > { > } > > (For code to be truly portable, NULL must be cast to the appropriate pointer > type every time it is used since it is nothing more than an integer bit > pattern :-) If the smiley really means "I don't believe the statement that precedes the smiley", OK; however, the statement in question is completely false. Any valid C compiler will turn foobar != 0 into a comparison of "foobar" with the appropriate representation for a null pointer of type "pointer to Foobar". > Why not just adopt a pattern of all zeroes as NULL instead? Just ensure > that this convention is observed by your malloc. Then we can write > > if (func) > result = (*func)(); > > rather than using double negatives: > > if (func != (int(*)(void))NULL) > result = (*func)(); "if (func != (int(*)(void))NULL)" is equivalent to "if (func != NULL)", because the compiler will perform the type conversion. "if (func != NULL)" is equivalent to "if (func != 0)", because "NULL" is supposed to be defined as "0" (or "(void *)0", but the latter isn't really necessary). "if (func != 0)" is equivalent to "if (func)". Therefore, you can write "if (func)" instead of "if (func != (int(*)(void))NULL)" *regardless* of the representation of a null pointer. The confusion on this point probably results because C did not have function prototypes until some compiler vendors put them in in anticipation of ANSI C. Thus, while the compiler has enough information to know that NULL (or 0, it's the same thing) in "foobar = NULL" or "if (func != NULL)" should be converted to the appropriate pointer type, the compiler lacks enough information to do the type conversion in "setbuf(stdout, NULL)" - it doesn't know that the second argument to "setbuf" is "char *". Therefore, you have to tell the compiler to perform this conversion by explicitly casting the pointer: "setbuf(stdout, (char *)NULL)". If you have function prototypes in your C implementation, and have included the proper include files or have otherwise arranged that prototypes are in scope for all functions to which you refer, the compiler can do the conversion: void setbuf(FILE *stream, char *buf); ... setbuf(stdout, NULL); Please don't post a followup to this article unless you have good evidence that the C *language* doesn't specify that the appropriate conversions be done in the examples given. Thank you.