NULL question not in FAQ

Chris Torek torek at elf.ee.lbl.gov
Wed Mar 27 20:34:39 AEST 1991


In article <1991Mar26.235643.4498 at ux1.cso.uiuc.edu> phil at 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 <machine/cpu.h>

	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 <char> 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 at ee.lbl.gov



More information about the Comp.lang.c mailing list