mark@navtech.uucp (Mark Stevans) (06/24/88)
So far, most responders to the article I posted on Wednesday have not addressed my question. I am not asking about what is a legal definition of NULL. I am asking whether one should define NULL in a product-wide header file *just* so that people won't have to include <stdio.h> if they only need a definition of "NULL" in a module. Perhaps I am partially at fault: to avoid prejudicing responses one way or the other, I gave the question without presenting any guiding arguments for either side. Here are some arguments to start us off on the right track (my personal opinion should now become obvious): Pros: Assuming you don't need to use the standard I/O library in a module, compilation will be slightly faster if you could leave out "stdio.h" and still have "NULL" defined. You should never include something you don't need, so if you are not actually using the standard I/O library in a module, you shouldn't have to include it. Cons: For reasons of portability and style, you should never create your own copies or versions of system-dependent constants unless the system header definition is incorrect or otherwise unusable. I know that some say NULL is system-dependent, while some say it is not. Ignore this one item if you favor the latter, but please *do not* mutate my posting into an argument about various definitions of NULL. Like it or not, <stdio.h> actually contains two completely separate things: it defines the structures and declares the external variables of the standard I/O library, *and* it defines "NULL". So if you need either one, you should include <stdio.h>. It contains no definitions (as opposed to declarations), so including it will never increase the size of your compiled code (except possibly a few words of debugging symbol space in the object file). Thus, including it never does any harm. The fraction of a second you save in compile time by not including <stdio.h> is insignificant. Even if you think you will not need the standard I/O library in some particular module, you or some later maintainer might someday insert an error message or debugging statement like "fprintf(stderr, ...)" or open a file with "fopen", and it will fail to compile until you edit the file to re-include <stdio.h>, thus wasting far more programmer and compilation time in one fell swoop than you previously saved by not including it. In general, this falls completely in the category of "micro-optimizations", where one puts emphasis on optimizing tiny details while overlooking the big picture. A personal message to Guy Harris at Sun: I'd love to see your analysis of this -- I encountered this idea first at a company I will not name -- the one we both worked at as of the beginning of 1984 (though I was at their main facility). Mark "The Shark" Stevans
g-rh@cca.CCA.COM (Richard Harter) (06/24/88)
In article <162@navtech.uucp> mark@navtech.uucp (Mark Stevans) writes: >So far, most responders to the article I posted on Wednesday have not addressed >my question. I am not asking about what is a legal definition of NULL. I am >asking whether one should define NULL in a product-wide header file *just* so >that people won't have to include <stdio.h> if they only need a definition of >"NULL" in a module. Mark summarizes arguments pro and con. I won't argue one way or the other as to whether it's the right thing to do, but here's what we did and why. In our standard header file we define null as 0 (note lower case) with the standard meaning that it is a null pointer. This takes care of all conflict problems without playing ifdef games at the price, of course, of adding a nonstandard keyword. We specifically rejected the notion of including stdio.h in all files, partly on methodological prejudices, and partly because our software runs on a variety of operating systems. Fopen and kin vary in treatment across operating systems; life is much simpler if calls to these routines are carefully isolated and are explicitly noted. -- In the fields of Hell where the grass grows high Are the graves of dreams allowed to die. Richard Harter, SMDS Inc.
swarbric@tramp.Colorado.EDU (Frank Swarbrick) (06/24/88)
Someone already pointed out that ANSI has NULL defined in stddef.h. In Turbo C 1.5 it is in both stdio.h and stddef.h. If I only need NULL I just include stddef.h. All that Turbo C's stddef does is typedefs size_t and ptrdiff_t, defines NULL (as 0 or 0L, depending on memory model) and declares errno as an external variable. Sounds quite reasonable to me. It's only 40 lines, and most of that is preprocessing stuff. Frank Swarbrick (and, yes, the net.cat) swarbric@tramp.Colorado.EDU ...!{ncar|nbires}!boulder!tramp!swarbric "And Jesus -- he wants to go to Venus."
karish@denali.stanford.edu (Chuck Karish) (06/24/88)
In article <6821@sigi.Colorado.EDU> swarbric@tramp.Colorado.EDU (Frank Swarbrick) writes: >Someone already pointed out that ANSI has NULL defined in stddef.h. In Turbo C >1.5 it is in both stdio.h and stddef.h. If I only need NULL I just include >stddef.h. All that Turbo C's stddef does is typedefs size_t and ptrdiff_t, >defines NULL (as 0 or 0L, depending on memory model) and declares errno as an >external variable. ANSI C requires that compilers allow headers to be #included more than once, with the same result that would have been produced by doing it once. Thus, <stdio.h> can #include <stddef.h> without worrying about whether the programmer uses that header a second time. This doesn't work in all historical implementations. For example, the IBM XENIX compiler complains about multiple definitions. In addition, that system defined NULL to be (char *)0 (it doesn't have void pointers). Lint and cc complain if 0 is used for NULL; I think they say "illegal combination of pointer and integer" for some reasonable constructs. The pickiness of the XENIX compiler is often helpful. Programs that run on it are usually very portable to other System V environments. Chuck Karish ARPA: karish@denali.stanford.edu BITNET: karish%denali@forsythe.stanford.edu UUCP: {decvax,hplabs!hpda}!mindcrf!karish USPS: 1825 California St. #5 Mountain View, CA 94041
devine@cookie.dec.com (Bob Devine) (06/25/88)
navtech!mark wrote: > I am not asking about what is a legal definition of NULL. I am > asking whether one should define NULL in a product-wide header file *just* so > that people won't have to include <stdio.h> if they only need a definition of > "NULL" in a module. Quick answer: "It depends". If every file is including stdio.h (or stddef.h for ANSI-C) anyway then what is the use of having another include file? This all devolves to the point that some common file *has* to be included anyway: yours or the standard file. However if you already do have a project-wide include file, you could make your own definition for NULL (you can choose any value for it as long as it is 0 ;-) But then I never use NULL. I use 0 cast appropriately because that is both correct and, I believe, more informative to readers. There is no single definition of NULL that is portable and correct in every situation. A cast must be used in some situations on some machine for some functions. Casts in C are easy to write. Bob Devine
guy@gorodish.Sun.COM (Guy Harris) (06/29/88)
> A personal message to Guy Harris at Sun: I'd love to see your analysis of > this -- I encountered this idea first at a company I will not name -- the > one we both worked at as of the beginning of 1984 (though I was at their main > facility). Oh, you mean CCI? If I'm writing code that includes some include file that defines NULL, I use it; otherwise, I use 0. I don't pull in e.g. <stdio.h> just to define NULL; however, most of the code I write is either 1) in the kernel, in which case it usually includes <sys/param.h> for other reasons and gets NULL predefined or 2) not in the kernel, but uses standard I/O, in which case it includes <stdio.h> and gets NULL predefined. Had I an ANSI C environment I'd include <stddef.h> and get it defined that way.