Path: utzoo!mnetor!uunet!mcvax!ukc!stc!stl!scott From: scott@stl.stc.co.uk (Mike Scott) Newsgroups: comp.lang.c Subject: Re: Why NULL is 0 Message-ID: <636@acer.stl.stc.co.uk> Date: 15 Mar 88 11:30:51 GMT References: <2550049@hpisod2.HP.COM> <7412@brl-smoke.ARPA> <3351@chinet.UUCP> <10574@mimsy.UUCP> <10576@mimsy.UUCP> Reply-To: scott@acer.UUCP (Mike Scott) Organization: STL,Harlow,UK. Lines: 66 In article <10576@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes: .... >of type (char *), are 48 bits wide. All other pointers, such as >(int *) and (double *), are 32 bits wide. > >Now suppose we have the following C code: > > main() > { > f1(NULL); /* wrong */ > f2(NULL); /* wrong */ > exit(0); > } > > f1(cp) char *cp; { if (cp != NULL) *cp = 'a'; } > f2(dp) double *dp; { if (dp != NULL) *dp = 2.2; } > >There are two lines marked `wrong'. Now suppose we were to define NULL >as 0. Clearly both calls are then wrong: both pass `(int)0', when the >first should be a 48 bit (char *) nil pointer and the second a 32 bit >(double *) nil pointer. > He suggests the form: > main() > { > f1((char *)NULL); > f2((double *)NULL); > exit(0); > } > >The preprocessor changes both NULLs to 0s, and the code remains >correct. > If I could add my 2 pennyworth. From K&R p192, we read " it is guaranteed that assignment of the constant 0 to a pointer will produce a null pointer distinguishable from a pointer to any object". From page 71: "Within a function, each argument is in effect a local variable initialized to the value with which the function was called." It follows at once from these that the integer 0 may be supplied in any function call where a pointer is expected, and the compiler must make sure that the proper translation to the correct sort of null pointer is performed. [I suppose one might argue about differences between 'assignment' and 'initialisation'. I think it's clear that initialisation of a pointer to NULL (whatever NULL may be defined as) and assignment of NULL to that same pointer have to give the same result!] The real problem is that functions don't have to be declared until used. Given an ANSII-type declaration, the compiler can sort out the mess. Until then, I suppose the only way to get portable code is indeed to use expicit casts as in the "correct" code above. But until now, I had no idea that machines with different pointer lengths existed [I'm rather blinkered by my PDP8/PDP11/VAX spectacles]. I don't really see how one can guess the needs of various 'strange' machine architectures that may exists :-( (Usual disclaimers apply.) -- Regards. Mike Scott (scott@stl.stc.co.uk ...uunet!mcvax!ukc!stl!scott) phone +44-279-29531 xtn 3133.