Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!mcvax!ukc!eagle!icdoc!cl-jenny!am From: am@cl.cam.ac.uk (Alan Mycroft) Newsgroups: comp.lang.c,news.software.b Subject: Re: passing NULL to functions Message-ID: <703@jenny.cl.cam.ac.uk> Date: Fri, 1-May-87 06:13:02 EDT Article-I.D.: jenny.703 Posted: Fri May 1 06:13:02 1987 Date-Received: Sat, 9-May-87 09:42:39 EDT References: <150@sds.UUCP> <1129@ius2.cs.cmu.edu> <5804@brl-smoke.ARPA> Reply-To: am@cl.cam.ac.uk (Alan Mycroft) Organization: U of Cambridge Comp Lab, UK Lines: 38 Xref: mnetor comp.lang.c:2101 news.software.b:601 In article <5804@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) ) writes: >In article <1129@ius2.cs.cmu.edu> edw@ius2.cs.cmu.edu (Eddie Wyatt) writes: >> Are you saying that you are not guarenteed sizeof(char *) == sizeof(int *) >>sizeof(long *) == sizeof(whatever *)? > >Yup. Very reasonable. As other correspondents pointed out elsewhere this has ramifications w.r.t. passing NULL to non-prototype functions. If sizeof(int *) != sizeof(char *)t hen *NO* definition of NULL (in the ANSI draft as it stands) can allow correct compilation of (the by suposition buggy, but common, code): #include extern void f(); /* or implicit, or varargs prototype */ g() { f(NULL,NULL); } if the actual definition of f was: void f(x,y) int *y; char *y; { ... } The problem is that the user is currently required to cast NULL to correct pointer types for non-prototype functions. As I pointed out to ANSI, one alternative suggestion is "If a function (f above) has no prototype in scope, or a varargs part of a prototype then all pointer arguments are widened to (void *)." Correspondingly, a function defined by void f(x,y) int *y; char *y; { ... } will need to generate relevant narrowing code (this would always be null on vax-like machines). In this case NULL is only sensibly defined as ((void *)0). This always works, both for prototype and non-prototype forms. The only thing to watch out for is that varargs functions will need to use (type *)va_next(ap, void *) rather that va_next(ap, type *). To convince the world that this is not unreasonable, just consider the exactly analogous situoutation with 'float' and 'double' (in this role (type *) and (void *) repectively). prototype in scope: float (effectively) left alone) prototype not in scope: float widened to double on call, narrowed on entry.