Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!mimsy!chris From: chris@mimsy.UUCP (Chris Torek) Newsgroups: comp.lang.c Subject: Re: pointer debate raging on... Message-ID: <6534@mimsy.UUCP> Date: Sat, 2-May-87 02:51:45 EDT Article-I.D.: mimsy.6534 Posted: Sat May 2 02:51:45 1987 Date-Received: Sun, 3-May-87 04:26:05 EDT References: <149@sds.UUCP> <17446@sun.uucp> <917@viper.UUCP> Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742 Lines: 115 In article <917@viper.UUCP> john@viper.UUCP (John Stanley) writes: >The answer to this was given in my original reply. The only pointer >type which is data nonspecific is void*, It is still specific: It is, specifically, the largest pointer type the compiler understands. That is, it represents the pointer type that has the most bits, and that can therefore represent all other pointers distinctly, so that any other pointer can be converted to (void *), then converted back, without losing any information. >thus NULL should be ((void*)0). Perhaps; but this will not solve the general case. It is correct to say that the integer constant zero is not a pointer type. It is NOT true to say that there is only one pointer type (whether John meant to imply this is unclear to me). Given that there are (theoretically) an infinite number of different pointer types, with (theoretically) infinite numbers of different representations, it is then obvious that there is no single kind of nil pointer: There are (theoretically) an infinite number of nil pointers, each as different from one another as a float is different from an unsigned short. Now an infinite number of different nil pointers should make it obvious that any single definition of NULL will not suffice. But in fact any one compiler does *not* provide an infinite number of different nil pointers. Indeed, in most compilers, there is only one nil pointer; in some, there are two, or three; there may even exist a compiler now that has more than three. I would guess that there are no compilers now with more than nine different kinds of nil, to wit, (char *)0, (short *)0, (int *)0, (long *)0, (float *)0, (double *)0, (struct any *)0, (union any *)0, (any (*)())0. So nine definitions of NULL should do, right? Wrong. There is nothing in the C language definition that limits the number of kinds of nil pointers, and someone designing a system and a compiler is free to invent new ones: (struct 0to3bytes *)0, (struct 4to15bytes *)0, ... and so forth. Providentially (and if you believe that...), C provides a single `unformed' nil pointer that may be converted to any of the infinite different true nil pointers. If this generic nil pointer were the word `nil', people might not assume it happened to be a zero-valued `int'. Alas, this generic nil pointer is the integer constant value 0, not the word nil. It is easy to tell from context when what appears to be a zero is in fact a specific nil pointer, and compilers use these contexts to convert the one to the other. These contexts include assignments to pointers, tests on pointers, and casts. They do *not* include function calls. Exercise: For each of the following, decide whether there is enough context to allow a compiler to convert the integer constant zero to an appropriate nil pointer: % cat example.c f() { char *cp; int i, *ip; extern int a; 1. cp = 0; 2. i = 0; cp = (char *) i; 3. ip = 0 * a; 4. if (cp != 0) { ... } 5. if (!ip) { ... } 6. if (ip == (char *) i) { ... } 7. g(0); /* assuming g takes one `long *' */ 8. g((long *) 0); } % ANSWERS (no peeking! and poking is frowned upon too :-) ): 1. yes 2. no 3. PCC complains, and one can argue either way 4. yes 5. yes 6. no 7. no 8. yes (I would say the answer to 3 is `yes', but one could argue that this is not an integer constant expression, since not all the subexpressions are constant. Oddly enough, PCC reduces the expression internally, but not until after deciding it is not a constant expression.) With the addition of function prototypes, the call to g in 7. can become correct: f() { ... int g(long *); ... g(0); } as this is now an assignment context. No matter what the definition of NULL---0 or (char *)0 or (void *)0 or whatever---there will be some situation in which this by itself is not appropriate. (The stubborn cases are functions with variable argument lists). A solution that works every time is to cast to the appropriate kind of nil pointer the integer constant zero (or, in dpANS C, the nil pointer to nothing `(void *)0') everywhere it appears. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690) Domain: chris@mimsy.umd.edu Path: seismo!mimsy!chris