[comp.std.c] legality of assignment of function to a void *.

lijewski@theory.tn.cornell.edu (Mike Lijewski) (11/13/90)

Is a standard conforming compiler required to issue an error
diagnostic for the following code.  Thanks.

#include <stdio.h>

double f(double x) { return x * x; }

int main(void)
{
   void *ptr = f;
   return 0;
}

-- 
Mike Lijewski  (H)607/272-0238 (W)607/254-8686
Cornell National Supercomputer Facility
ARPA: lijewski@theory.tn.cornell.edu  BITNET: mjlx@cornellf.bitnet
SMAIL:  25 Renwick Heights Road, Ithaca, NY  14850

gwyn@smoke.brl.mil (Doug Gwyn) (11/13/90)

In article <1990Nov12.211511.2344@batcomputer.tn.cornell.edu> lijewski@theory.tn.cornell.edu (Mike Lijewski) writes:
>Is a standard conforming compiler required to issue an error
>diagnostic for the following code.  Thanks.

Certainly.  It violates a constraint in section 3.3.16.1.

henry@zoo.toronto.edu (Henry Spencer) (11/14/90)

In article <1990Nov12.211511.2344@batcomputer.tn.cornell.edu> lijewski@theory.tn.cornell.edu (Mike Lijewski) writes:
>Is a standard conforming compiler required to issue an error
>diagnostic for the following code.  Thanks.
>
>double f(double x) { return x * x; }
>   void *ptr = f;

Function pointers are a whole different universe from normal pointers, in
principle.  Free conversions to and from `void *' are allowed only for
normal pointers (see 3.3.16.1 and the cross-reference to it in 3.5.7).
Your example is not in the list of allowable combinations of operands
for `=' in 3.3.16.1's Constraints section, so you are breaking the law
and the compiler is required to diagnose it, unless I have missed some
subtlety.

Your compiler might choose to allow `void *ptr = (void *)f;', however,
as an extension.
-- 
"I don't *want* to be normal!"         | Henry Spencer at U of Toronto Zoology
"Not to worry."                        |  henry@zoo.toronto.edu   utzoo!henry

tada@athena.mit.edu (Michael J Zehr) (11/14/90)

In article <1990Nov13.174920.2235@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes:
>In article <1990Nov12.211511.2344@batcomputer.tn.cornell.edu> lijewski@theory.tn.cornell.edu (Mike Lijewski) writes:
>>double f(double x) { return x * x; }
>>   void *ptr = f;
>
>Function pointers are a whole different universe from normal pointers, in
>principle.

I've tried to follow the new ansi rules pretty carefully and I wasn't
aware of this until recently when it was pointed out here(*).  My main
source of confusion was K&R2 (p. 199, "Any pointer may be converted to
type void * without loss of information.  If the result is converted
back to the original pointer type, the original pointer is recovered.")

This seems very misleading to me.  (Yes, I know that K&R2 is not the
official ANSI specification for C.)  Does anyone know if this was
something that was changed after K&R2 was written?  What about other
statements in K&R2 that are misleading or conflict with the standard?

-michael j zehr

(*) And fortunately or unfortunately, depending on how you look at it, I
do most of my work on a VAX, where a pointer is a pointer is a pointer,
so I never had problems with any code I wrote, nor did the compiler ever
complain.

blodgett@apollo.HP.COM (Bruce Blodgett) (11/17/90)

Sorry if this is a repost - my previous attempt apparently never made
it to the net  -- Bruce Blodgett

In article <1990Nov14.031125.14027@athena.mit.edu> tada@athena.mit.edu (Michael J Zehr) writes:
>In article <1990Nov13.174920.2235@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes:
>>In article <1990Nov12.211511.2344@batcomputer.tn.cornell.edu> lijewski@theory.tn.cornell.edu (Mike Lijewski) writes:
>>>double f(double x) { return x * x; }
>>>   void *ptr = f;
>>
>>Function pointers are a whole different universe from normal pointers, in
>>principle.
...
>                        K&R2 (p. 199, "Any pointer may be converted to
>type void * without loss of information.

And in article <14450@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
>Certainly.  It violates a constraint in section 3.3.16.1.

The relevant portion of the constraint from section 3.3.16.1 is:
one operand is a pointer to an object or incomplete type and the other
is a pointer to ... *void*

Section 3.2.2.1 states:
A *function designator* is an expression that has function type.
Except when it is the operand of the sizeof operator or the unary &
operator, a function designator with type "function returning *type*"
is converted to an expression that has type "pointer to function
returning *type*."

Section 3.1.2.5 defines *object types* as:
types that describe objects

Section 1.6 defines *object* as:
a region of data storage ...
            ^^^^
Section 3.1.2.5 defines *incomplete types* as:
types that describe objects but lack information needed to determine
their sizes

Functions are neither objects nor incomplete types, and
pointers to functions are neither pointers to objects nor to
incomplete types.  Never-the-less, functions do have addresses.
Was it really the intent of the ANSI C committee not to allow void
pointers from holding uncasted function addresses (in either
conforming or strictly conforming programs)?
Bruce Blodgett
blodgett@apollo.hp.com
(508) 256-0176 x4037

henry@zoo.toronto.edu (Henry Spencer) (11/17/90)

In article <4e0cac89.20b6d@apollo.HP.COM> blodgett@apollo.HP.COM (Bruce Blodgett) writes:
>Was it really the intent of the ANSI C committee not to allow void
>pointers from holding uncasted function addresses (in either
>conforming or strictly conforming programs)?

Yes.  A void pointer, for compatibility reasons, is constrained to have
the same representation as a character pointer.  Pick a sufficiently
outre' machine, and function pointers may well be bizarre and complex
objects too large to fit in any reasonable data pointer.  A function
pointer is **not** (necessarily) the address of the function; functions
may not even have "addresses" in any simple sense, and calling a function
may require considerably more information than just where to find the code.
-- 
"I don't *want* to be normal!"         | Henry Spencer at U of Toronto Zoology
"Not to worry."                        |  henry@zoo.toronto.edu   utzoo!henry

gwyn@smoke.brl.mil (Doug Gwyn) (11/17/90)

In article <4e0cac89.20b6d@apollo.HP.COM> blodgett@apollo.HP.COM (Bruce Blodgett) writes:
>Was it really the intent of the ANSI C committee not to allow void
>pointers from holding uncasted function addresses (in either
>conforming or strictly conforming programs)?

There seems to be general agreement among the X3J11 members I've discussed
this with that void* need not be capable of holding pointer to function.
A strictly conforming program could not so use it.  A conforming program
can do whatever it can get away with.  Conforming implementations have the
option whether or not to support the property in question.  I would expect
that only those environments requiring more data to specify function
pointers than to specify object pointers would impose the restriction.
(Well, also environments intended to assist in developing strictly
conforming programs.)

steve@taumet.com (Stephen Clamage) (11/18/90)

tada@athena.mit.edu (Michael J Zehr) writes:

>In article <1990Nov13.174920.2235@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes:
>>Function pointers are a whole different universe from normal pointers, in
>>principle.

>I've tried to follow the new ansi rules pretty carefully and I wasn't
>aware of this until recently when it was pointed out here....  My main
>source of confusion was K&R2 ...
>(Yes, I know that K&R2 is not the
>official ANSI specification for C.)  Does anyone know if this was
>something that was changed after K&R2 was written?

It was not changed after K&R2 -- I don't have a copy of the book, but
is it possible that there is a larger context where they stated they
were discussing pointers to data objects?

>What about other
>statements in K&R2 that are misleading or conflict with the standard?

K&R2 is not the standard.  The standard is ANSI X3.159-1989.  If you
find misleading or conflicting statements in any book, you should
notify the author(s) (presumably via the publisher).
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

steve@taumet.com (Stephen Clamage) (11/18/90)

blodgett@apollo.HP.COM (Bruce Blodgett) writes:

>Was it really the intent of the ANSI C committee not to allow void
>pointers from holding uncasted function addresses (in either
>conforming or strictly conforming programs)?

Yes.  On some implementations it may not be possible (or at least not
reasonable) to cast a function pointer to a void*.  For a simple
example, consider a program on a PC in large-code-small-data model.
A function pointer is then 32 bits, but a void* is 16 bits.  One purpose
of the standard is to explain what programs can be run safely on all
conforming implementations.
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

tt@tarzan.jyu.fi (Tapani Tarvainen) (11/18/90)

If I want a variable to be able to hold pointers to different
functions, do I have to use union and list all function types I want,
or can I assume all function pointers are similar and can (with
suitable cast) be assigned to variables of different function pointer
type safely?  Or is there some funtion pointer type that can be relied
on to be bigger than and thus able to hold any other?

Example:  A hypothetical compiler for 80x86 tries to put all functions
of the same type in the same segment and if they fit, uses 16-bit
pointers for them (and for each call generates code that uses the
correct segment), otherwise 32-bit ones.  
Would it be standard-conforming?
--
Tapani Tarvainen    (tarvaine@jyu.fi, tarvainen@finjyu.bitnet)

martin@mwtech.UUCP (Martin Weitzel) (11/19/90)

In article <1990Nov14.031125.14027@athena.mit.edu> tada@athena.mit.edu (Michael J Zehr) writes:
[function pointers beeing completly different creatures than data pointers]

>My main
>source of confusion was K&R2 (p. 199, "Any pointer may be converted to
>type void * without loss of information.  If the result is converted
>back to the original pointer type, the original pointer is recovered.")
>
>This seems very misleading to me.  (Yes, I know that K&R2 is not the
>official ANSI specification for C.)

Yes, it seems a problem fopr me too that there are some "references" which
in general appear well-trustable (like K&R-II) but fail to specify a few
not so well known portability traps.

How about adding a list of such things to the FAQ in c.l.c? I think
this would be helpful to the vast majority, who either can't afford
the X3.159-1989 document because of the high price, or who don't have
the time and patience to read it very very carefully.

The problem may be that such a list should not degenerate into
(another) specification of ANSI C, but that is not be so hard to
avoid if we leave out all things, that are obvious from K&R-II,
or rather esoteric.
-- 
Martin Weitzel, email: martin@mwtech.UUCP, voice: 49-(0)6151-6 56 83

henry@zoo.toronto.edu (Henry Spencer) (11/20/90)

In article <TT.90Nov18144547@tarzan.jyu.fi> tt@tarzan.jyu.fi (Tapani Tarvainen) writes:
>If I want a variable to be able to hold pointers to different
>functions, do I have to use union and list all function types I want,
>or can I assume all function pointers are similar and can (with
>suitable cast) be assigned to variables of different function pointer
>type safely? ...

The standard guarantees that you can convert one kind of function pointer
to another and back and get a pointer equal to the original (3.3.4).  So
you can use any function-pointer type to store pointers to arbitrary
functions.  However, you must convert the pointer to the correct type
for the function it points to before using it, or the result is undefined.
-- 
"I don't *want* to be normal!"         | Henry Spencer at U of Toronto Zoology
"Not to worry."                        |  henry@zoo.toronto.edu   utzoo!henry