Void* Problem in BT
Chris Torek
torek at elf.ee.lbl.gov
Sat Mar 2 12:49:11 AEST 1991
(catching up on old news, Feb 6?!)
In article <43818 at nigel.ee.udel.edu> boutell at freezer.it.udel.edu
(Tom Boutell) writes:
>void broadcast(messagetype,details)
> char messagetype;
> void* details;
>{
>... [when using `details'] some folks' C compilers report that details
>is undefined and give up.
>Can anyone explain why this is so?
Easy :-)
The people whose compilers say
"foo.c", line 1234: details undefined
are using versions of PCC (or descendents thereof) in which the `void'
type's number is unchanged since `void' was first added to the compiler
(`void' appeared in 4.0BSD but not in 3BSD, for instance.)
Whoever originally added `void' added it as a special case, and gave it
a type number that corresponds to `UNDEF'. (Actually, it got a
slightly schizophrenic type; TVOID is FTN while void is UNDEF; but
this is a different problem entirely.) The variable declaration code
is careful to reject `void' variables:
if( type == UNDEF ) uerror("void type for %s",p->sname);
but it does not check for pointers to UNDEF as generated by INCREF(UNDEF)
(actual value 020) or pointers to pointers to void (INCREF(INCREF(UNDEF))),
etc.
Now, the symbol table code uses a special value, TNULL, to mark slots in
the symbol table that are free. TNULL is defined as an `impossible'
type:
#define TNULL PTR /* ptr to UNDEF */
The actual value of TNULL is 020---the same value as produced by
INCREF(UNDEF)
which is the value produced for a declaration of the form:
void *p;
In other words, in these PCC-based compilers, `void *p;' carefully
allocates a symbol table entry, sets up sizes, offsets, and so forth,
and then sets the symbol table's type to a value meaning `this symbol
table slot is empty'. When you ask for the name, the symbol table
hashing code dutifully locates the proper slot and sees TNULL and says,
`oh, this slot is empty; I guess the name was not defined after all'.
The right fix for the compiler is somewhat complicated. The workaround
is simpler, but `#define void char' is NOT it.
One straightforward workaround is to define:
typedef void *PTR;
or
typedef char *PTR;
and then use `PTR' exclusively to obtain a generic pointer. You must
also add casts:
f(p) PTR p; {
struct foo *actual;
...
actual = p;
}
will produce at least a warning if `PTR' is an alias for `char *':
actual = (struct foo *)p;
suppresses this.
--
In-Real-Life: Chris Torek, Lawrence Berkeley Lab EE div (+1 415 486 5427)
Berkeley, CA Domain: torek at ee.lbl.gov
More information about the Comp.unix.programmer
mailing list