Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!zaphod.mps.ohio-state.edu!sdd.hp.com!caen!uwm.edu!linac!att!ucbvax!dog.ee.lbl.gov!elf.ee.lbl.gov!torek From: torek@elf.ee.lbl.gov (Chris Torek) Newsgroups: comp.lang.c Subject: Re: NULL question not in FAQ Message-ID: <11510@dog.ee.lbl.gov> Date: 27 Mar 91 10:34:39 GMT References: <1991Mar26.235643.4498@ux1.cso.uiuc.edu> Reply-To: torek@elf.ee.lbl.gov (Chris Torek) Organization: Lawrence Berkeley Laboratory, Berkeley Lines: 120 X-Local-Date: Wed, 27 Mar 91 02:34:39 PST In article <1991Mar26.235643.4498@ux1.cso.uiuc.edu> phil@ux1.cso.uiuc.edu (Phil Howard KA9WGN) writes: >Given that the compiler is supposed to translate the constant "0" to the >appropriate value for a NULL pointer on the machine type, how does one >get a pointer value whose representation happens to be all zeroes, but >is a non-NULL pointer? In standard C, one simply writes: p = &obj; or p = malloc(size); or whatever, and it Just Happens to return a value whose representation is all-zero-bits, yet compares unequal to 0. Outside the standard, there is no way to say how one will do it, precisely *because* one is outside the standard. In order to describe the rules, one must first know them. That said---warning: opinion follows---the best way for an implementor, faced with such a machine, to allow O/S programmers and similar ilk access to the Special Stuff at machine address 0, despite the fact that nil pointers to types T1, T2, and T3 must be nonzero bit patterns, is to make struct foo *p; long l = 0; p = l; `do the right thing'. Another entirely acceptable alternative is: #include volatile union zeropointer z; ... zeropointer(&z); /* point to machine address 0 */ z.ptr->zp_frammitz = 1; /* turn on the frammitz */ >Are all of these equivalent or are any differnt? > > p = ( (char *) 0 ); > p = ( (char *) 00 ); > p = ( (char *) 0x0 ); > p = ( (char *) 0x00 ); These are all equivalent. > p = ( (char *) 1-1 ); This is not, but only because the cast binds more tightly; p = (char *)(1 - 1); *is* equivalent to the other four assignments above, but p = (char *)1 - 1; is unpredictable. It might be another way to get an all-bits-zero pointer value, but it might not (perhaps all `char *' pointers have the low 2 bits set indicating a tag, so this might give a pointer that happens to have the integer value `3'). This is another acceptable, but machine dependent (as always), method of obtaining an `all zero bits pointer'. >Suppose I do this: > > char *p; > int i; > p = NULL; > i = (int) p; > >Will I get a value of zero in "i" always, regardless of the way the >machine type represents a NULL? No. >I am wanting to discern whether or not the special case of a pointer value >being translated to the NULL representation is done with the particular >constant of a single digit "0" or if it is done with ANY constant whose >integer value is numerically 0. A null pointer to some type T is produced by writing the integer constant 0 (i.e., any constant expression whose type is integral and whose value is zero) in the appropriate pointer context. In other words, it is `any constant', not just the single digit `0'. Note that some expressions that are immutable are not actually `constant expressions', e.g., (""[0]) is immutably% 0, yet it is not an `integer constant zero' by ANSI rules. A compiler is allowed, but not required, to treat it as if it were just `0'. ----- % Well, you can sometimes persuade it not to be 0 if you do something illegal, like scribble on your text segment. ----- Incidentally, one simple method for getting an arbitrary machine- dependent pointer value, without gimmicking the compiler or using unions or any such other grotesqueries, is to use assembly code. For instance: extern struct cypripareunia s; combined with: .set _cypripareunia, 0 or _cypripareunia = 0 will often do the trick. (Those of you who look up this word, or [shudder :-) ] know if offhand, will see what I think of this. :-) ) -- In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427) Berkeley, CA Domain: torek@ee.lbl.gov