[comp.lang.c] Let's define our own NULL II

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.