[comp.lang.c] Invalid Pointers

les@chinet.chi.il.us (Leslie Mikesell) (07/18/89)

In article <10541@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:

>-#define NO_FOOBAR ((struct foobar *) -1 )	is what I use, but...

>This is not portable.  Just use NULL.

Do you mean that there are machines that might return a valid -1 from
sbrk(2) or shmat(2), or that would misconstrue the comparsion of
a pointer to -1?  Yes, I know these are botches, but are they not
always accomodated?

Les Mikesell

chris@mimsy.UUCP (Chris Torek) (07/18/89)

(This is more a `unix' question than a `C' question; I have cross-posted
this and redirected followups back to comp.lang.c.)

>In article <10541@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
>>... Just use NULL.

In article <8990@chinet.chi.il.us> les@chinet.chi.il.us (Leslie Mikesell)
writes:
>Do you mean that there are machines that might return a valid -1 from
>sbrk(2) or shmat(2), or that would misconstrue the comparsion of
>a pointer to -1?  Yes, I know these are botches, but are they not
>always accomodated?

There are no existing machine/compiler combinations now running
System V that cannot handle this, as far as I know.  It is likely
that in at least one case this was acheived by slowing down everything
else for the sake of making the botches work.

It is worth noting (particularly in comp.unix.questions/INFO-UNIX, but
only once) that in C the integer constant `0' is *also* the untyped nil
pointer.  All other integer constant values are simply integer constant
values; zero is a special case.  Somewhere inside the guts of every C
compiler is some code that, in appropriate contexts, converts `integer
constant zero' to `nil pointer to T' for some type T.  Even on VAXen,
the special-case code must be there to decide whether to complain about
pointer/integer conversion.  This same special case code is free to alter
the value and/or number of bits in the resulting nil pointer to T, and
on some machines it does.

There are only two ways that the untyped nil pointer can acquire a
type, namely assignment and comparison.  Casts are a special case of
assignment, as are arguments to functions that have prototypes in
scope (`ANSI C').  Where this causes the most trouble is in arguments
to functions that do not have prototypes in scope, or for which the
prototype does not specify a type for that argument: e.g., execl():

	f() {
		void execl(char *, ...);

		execl("prog", "prog", "arg1", "arg2", ___);
	}

Languages like Pascal use the keyword `nil' for their untyped nil
pointers.  This has the advantage that it does not have any other
meaning, and the compiler can complain if it sees something like

		execl("prog", "prog", "arg1", "arg2", nil);

where the information needed to convert `nil' to `nil pointer to char'
is missing.  C compilers must simply assume that the fifth argument is
already correct, no matter what is written there---if you write `0'
without a cast, they will figure you meant the integer value zero.

It is also worth noting that while the integer value zero is made up of
a string of zero bits, a nil pointer (of any arbitrary type T) need not
be so.  The folks at the S-1 project (in LLL) tried to build such a
machine and put a Unix-derived system on it, but ran into so much
trouble from code that did not cast its `0' constants to nils that they
modified the hardware to allow it instead.  There are machines made
today in which the format of pointers to words and pointers to bytes
differ (e.g., Data General).  This causes similar grief to careless
programmers, because conversions between (char *) and (int *) (e.g.)
are no longer no-ops (they compile into shift-and-mask operations).

Both of these problems will never plague you if you are careful to
distinguish between integers and pointers, and between pointers to one
type and pointers to another.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

gwyn@smoke.BRL.MIL (Doug Gwyn) (07/19/89)

In article <8990@chinet.chi.il.us> les@chinet.chi.il.us (Leslie Mikesell) writes:
-In article <10541@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
->>#define NO_FOOBAR ((struct foobar *) -1 )	is what I use, but...
->This is not portable.  Just use NULL.
-Do you mean that there are machines that might return a valid -1 from
-sbrk(2) or shmat(2), or that would misconstrue the comparsion of
-a pointer to -1?

What I mean is what I said.

-Yes, I know these are botches, but are they not always accomodated?

No.  Non-UNIX systems need not even try to accommodate them.