[comp.unix.programmer] Void* Problem in BT

bhoughto@hopi.intel.com (Blair P. Houghton) (02/08/91)

In article <43818@nigel.ee.udel.edu> boutell@freezer.it.udel.edu (Tom Boutell) writes:
>void broadcast(messagetype,details)
>  char messagetype;
>  void* details;
>{
>      location* wherep;
>      wherep=(location*) details;
       ...
>
>Now, what happens is that in the line wherep=(location*) details; 
>some folks' C compilers report that details is undefined and give up.

Broken compiler, or one that does not have a concept of void?

`details' is very definitely defined at that point, provided
the compiler is one that knows of the keyword `void'.  Some don't.

Seems like there should be a lot of other warning bells, though,
like why it doesn't flag the syntax error due to `void* details'
if it can't swallow `void'.

Try putting

    #ifdef foo
    #define void char
    #endif

Where foo is a compiler-defined constant (you know, like
`apollo' or `vax' or `bsd') specific to that funky
compiler.  If the compiler doesn't know void, it's a fair
bet that (char *) is the proper generic pointer type.

				--Blair
				  "(void **)NULL."

moss@cs.umass.edu (Eliot Moss) (02/08/91)

Just an additional point -- there are compilers out there that understand void
as, for example, the result type of a function, but do not understand (void *)
properly. This might well be your situation. One compiler I know of that
does/did not implement void * is the MIPSco compiler, at least in earlier
releases (maybe fixed by now).					Eliot
--

		J. Eliot B. Moss, Assistant Professor
		Department of Computer and Information Science
		Lederle Graduate Research Center
		University of Massachusetts
		Amherst, MA  01003
		(413) 545-4206, 545-1249 (fax); Moss@cs.umass.edu

torek@elf.ee.lbl.gov (Chris Torek) (03/02/91)

(catching up on old news, Feb 6?!)

In article <43818@nigel.ee.udel.edu> boutell@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@ee.lbl.gov