functionpointer prototype with void* : question

A

Andreas Klimas

hello,

no many words, I will start with an example instead

int foo(void *r) {...}

void test(void) {
int *x=0;
foo(x); /* seems to me as valid */
}
--------------------------------------------------------------
int foo(void(*cb)(void*r)) {...}
void bar(int *x) {...}

void test(void) {
foo(bar); /* seems to me as valid, but not for the compiler */
}

the question now is hopefully obvious. why can't I assign
a functionpointer where the only difference is void* vs.
int* in its arguments. the direct way is allowed, but the
indirect isn't. do I miss any important point (i think so).

thanks

best wishes

Andreas Klimas
 
B

Barry Schwarz

hello,

no many words, I will start with an example instead

int foo(void *r) {...}

void test(void) {
int *x=0;
foo(x); /* seems to me as valid */

This is valid because there is a defined implicit conversion from int*
(the type of x) to void* (the type the function needs/expects in r).
}
--------------------------------------------------------------
int foo(void(*cb)(void*r)) {...}
void bar(int *x) {...}

void test(void) {
foo(bar); /* seems to me as valid, but not for the compiler */

This is not valid because there is no defined implicit conversion from
void(*)(int*) --the type of bar-- to void(*)(void*) -- the type the
function expects in cb, NOT r.
}

the question now is hopefully obvious. why can't I assign
a functionpointer where the only difference is void* vs.
int* in its arguments. the direct way is allowed, but the
indirect isn't. do I miss any important point (i think so).

Consider when sizeof(void*) != sizeof(int*). In the first example,
the compiler knows a) foo is expecting a void*, b) x is an int*, and
c) how to convert one to the other. It can generate the code with no
problem.

In the second example, the compiler may not know anything at all about
how foo uses its argument (foo could be in a library). Let us assume
it uses the argument to call the function pointed to. The code in foo
will generate an argument of type void* and pass it to bar. bar, on
the other hand, is expecting an int*. It will attempt to extract an
int* from however the argument is passed. Since the two types have
different sizes, it will not extract the correct data.
thanks

best wishes

Andreas Klimas


Remove del for email
 
J

Jack Klein

hello,

no many words, I will start with an example instead

int foo(void *r) {...}

foo() is a function accepting a pointer to void and returning an int.
void test(void) {
int *x=0;
foo(x); /* seems to me as valid */

Due to the prototype for foo() being in scope, the compiler converts
'x' to pointer to void, an allowed automatic conversion, and calls
foo(). No problem.

This time, foo() is a function that returns an int and accepts a
pointer to a function. That function pointer must point to a function
that accepts a pointer to void and returns nothing.
void bar(int *x) {...}

bar() is a function that returns nothing, but accepts a pointer to
int. The function signature is different.
void test(void) {
foo(bar); /* seems to me as valid, but not for the compiler */
}

the question now is hopefully obvious. why can't I assign
a functionpointer where the only difference is void* vs.
int* in its arguments. the direct way is allowed, but the
indirect isn't. do I miss any important point (i think so).

thanks

best wishes

Andreas Klimas

The automatic conversion from "pointer to any object type" to "pointer
to void", and the reverse, is a direct top-level conversion only.

The language does not allow the automatic conversion of
void(*)(object_type*) to void(*)(void*).

The language does not allow the automatic conversion of object_type
**x to void **y.

These are not direct conversions of object_type* to void*.

You can use a cast to do what you want, but note that the actual
parameters passed to the function when it is called through the
pointer must match the function's definition, or the behavior is
undefined.
 
B

Bill Pursell

Andreas said:
int foo(void *r) {...}

void test(void) {
int *x=0;
foo(x); /* seems to me as valid */
}
--------------------------------------------------------------
int foo(void(*cb)(void*r)) {...}
void bar(int *x) {...}

void test(void) {
foo(bar); /* seems to me as valid, but not for the compiler */
}

Note that you may get away with:

int foo(void *) {...}
void bar(int *x) {...}

foo(bar)

The conversion from void * to function pointer
is not guaranteed to work on all platforms, and is certainly
not guaranteed by the language, but it does
work on many.
 
K

Keith Thompson

Bill Pursell said:
Note that you may get away with:

int foo(void *) {...}
void bar(int *x) {...}

foo(bar)

The conversion from void * to function pointer
is not guaranteed to work on all platforms, and is certainly
not guaranteed by the language, but it does
work on many.

Passing a function pointer to a function expecting a void* is a
constraint violation; there's no implicit conversion from function
pointers to void*. An implementation can, as you say, accept it as an
extension -- but it must issue a diagnostic in conforming mode.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top