[comp.lang.c] void * compatibility

polfer@b11.ingr.com (? Polfer) (09/20/90)

While porting some code to an ANSI compiler (NOT porting to ANSI), I received 
an error with code similar to the following:

    int (**command)();

    ...

    *command = NULL;

The warning was:

    "Type `void *' is not assignment compatible with type `int (*)()'."

The compiler is not in full ANSI mode (we must keep using a non ANSI compiler
on another platform), so prototyping is NOT being used.  It turns out that 
Metaware High C defines NULL in stdio.h as "(void *)0".  This gives a little 
bit more error checking than just using "0".  My question is why the above 
code errors out.  "*command" is a pointer to a function which returns int, but
it is still a pointer.  I understand that ANSI does not guarantee that
pointers to different types will have the same internal repesentations, but
isn't a "void *" supposed to be assignment compatible with ALL pointers?  

The fix is to use "*command = (int (*)())0;" or just plain "*command = 0;",
neither of which yield errors.  Could this be because "0" is considered the
generic NULL pointer value while the explicit cast (void *) fouls the 
assignment?  Any ideas would be appreciated!

-----

Dan Polfer             uunet!ingr!b11!dap!dan  (UUCP)
                       b11!dap!dan@ingr.com    (Internet)

chris@mimsy.umd.edu (Chris Torek) (09/20/90)

In article <8770@b11.ingr.com> polfer@b11.ingr.com (? Polfer) writes:
>... "Type `void *' is not assignment compatible with type `int (*)()'."
>The compiler is not in full ANSI mode ... [and] Metaware High C
>defines NULL in stdio.h as "(void *)0".

The value ((void *)0) is a generic nil pointer, as well as being a
particular specific nil pointer, and any compiler that believes it
is not suitable in an (int (*)()) context is buggy (at least if the
compiler claims ANSI conformance).

Personally, I think defining NULL as (void *)0 is foolishness: if you
want your compiler to provide complete error checking, you should define
it as `__nil' and make __nil a keyword.  Using (void *)0 fixes a few
specific problems, but leaves others unfixed and unfixable.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 405 2750)
Domain:	chris@cs.umd.edu	Path:	uunet!mimsy!chris

karl@haddock.ima.isc.com (Karl Heuer) (09/20/90)

In article <8770@b11.ingr.com> polfer@b11.ingr.com (? Polfer) writes:
>    int (**command)();
>    *command = NULL;
>    "Type `void *' is not assignment compatible with type `int (*)()'."
>isn't a "void *" supposed to be assignment compatible with ALL pointers?

No, it's compatible with all *data* pointers.  Function pointers need not fit
in a `void *'.

But (as Chris Torek already pointed out), a null pointer constant is a special
case.  Your compiler has a bug in that it apparently fails to recognize the
`(void *)0' form as a null pointer constant.

Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint

henry@zoo.toronto.edu (Henry Spencer) (09/23/90)

In article <26628@mimsy.umd.edu> chris@mimsy.umd.edu (Chris Torek) writes:
>Personally, I think defining NULL as (void *)0 is foolishness: if you
>want your compiler to provide complete error checking, you should define
>it as `__nil' and make __nil a keyword.  Using (void *)0 fixes a few
>specific problems, but leaves others unfixed and unfixable.

Actually, the Rationale for ANSI C makes it clear that error checking had
nothing to do with making `(void *)0' an official null pointer.  The
motive was to provide for a NULL of the same size as most pointers --
thereby minimizing breakage of old defective code -- on machines where
there is no integer type of the right size.  Minimizing breakage is also
the reason why (e.g.) `0L' is also a legal NULL, for machines where
pointers are the size of longs rather than ints.
-- 
TCP/IP: handling tomorrow's loads today| Henry Spencer at U of Toronto Zoology
OSI: handling yesterday's loads someday|  henry@zoo.toronto.edu   utzoo!henry