By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,854 Members | 1,871 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,854 IT Pros & Developers. It's quick & easy.

call a function via a function pointer of different type

P: n/a
Hi all

Can one reliably call a function via a function pointer of different type
as below?

struct some_struct {
int some_int;
};

int some_function( struct some_struct *struct_ptr ){
return struct_ptr-some_int;
}

int main( void ){
struct some_struct a_struct= { 42 };
int (*function_pointer)(void*)= & some_function;

return (*function_pointer)( & a_struct );
}

Thanks,
viza
Oct 26 '08 #1
Share this Question
Share on Google+
5 Replies


P: n/a
viza <to******@gm-il.com.obviouschange.invalidwrites:
Can one reliably call a function via a function pointer of different type
Yes.
as below?
No! You can do it but not like this.
struct some_struct {
int some_int;
};

int some_function( struct some_struct *struct_ptr ){
return struct_ptr-some_int;
}

int main( void ){
struct some_struct a_struct= { 42 };
int (*function_pointer)(void*)= & some_function;
This initialisation requires a diagnostic but it is perfectly OK if
you supply a cast (and I prefer to have no & operator):

int (*function_pointer)(void*)= (int (*)(void *))some_function;
return (*function_pointer)( & a_struct );
and at this point you must convert the pointer to the type of the
function you are actually calling.

return ((int(*)(struct some_struct *))function_pointer)(&a_struct);

and, again, I prefer to omit the * (it turns the pointer into a
function which is converted back to pointer for the call -- at least
in modern C).
}
--
Ben.
Oct 26 '08 #2

P: n/a
Ben Bacarisse wrote:
>
This initialisation requires a diagnostic but it is perfectly OK if
you supply a cast (and I prefer to have no & operator):

int (*function_pointer)(void*)= (int (*)(void *))some_function;
In addition to what Ben said, it's useful to have typedef's for function
pointers. For example:
typedef int (*my_func_t)(void*);

....

my_func_t function_pointer;

....

function_pointer = (my_func_t) some_function;
and when calling:

function_pointer (&arg);
--
Tor <echo bw****@wvtqvm.vw | tr i-za-h a-z>
Oct 26 '08 #3

P: n/a
viza <tom.v...@gm-il.com.obviouschange.invalidwrote:
Hi all

Can one reliably call a function via a function pointer
of different type as below?
Depends on whether you think undefined behaviour is
reliable or not.
struct some_struct {
* int some_int;
};

int some_function( struct some_struct *struct_ptr ){
* return struct_ptr-some_int;
}

int main( void ){
* struct some_struct a_struct= { 42 };
* int (*function_pointer)(void*)= & some_function;
This violates a contraint.
* return (*function_pointer)( & a_struct );
}
Since some_function isn't variadic, and since struct
pointers aren't subject to promotion, you can portably
do...

int (*function_pointer)() = some_function;
return function_pointer( & a_struct );

--
Peter
Oct 27 '08 #4

P: n/a
Ben Bacarisse <ben.use...@bsb.me.ukwrote:
viza <tom.v...@gm-il.com.obviouschange.invalidwrites:
Can one reliably call a function via a function
pointer of different type

Yes.
as below?

No! *You can do it but not like this.
struct some_struct {
* int some_int;
};

int some_function( struct some_struct *struct_ptr ){
* return struct_ptr-some_int;
}

int main( void ){
* struct some_struct a_struct= { 42 };
* int (*function_pointer)(void*)= & some_function;

This initialisation requires a diagnostic but it is
perfectly OK if you supply a cast (and I prefer to
have no & operator):
int (*function_pointer)(void*)= (int (*)(void *))some_function;

* return (*function_pointer)( & a_struct );
Since some_function is not variadic, better is...

int (*function_pointer)() = some_function;
and at this point you must convert the pointer to the
type of the function you are actually calling.

* return ((int(*)(struct some_struct *))function_pointer)
(&a_struct);
With the non-prototype declaration, it's just...

return function_pointer(&a_struct);

--
Peter
Oct 28 '08 #5

P: n/a
Peter Nilsson <ai***@acay.com.auwrites:
Ben Bacarisse <ben.use...@bsb.me.ukwrote:
>viza <tom.v...@gm-il.com.obviouschange.invalidwrites:
Can one reliably call a function via a function
pointer of different type

Yes.
as below?

No! *You can do it but not like this.
struct some_struct {
* int some_int;
};

int some_function( struct some_struct *struct_ptr ){
* return struct_ptr-some_int;
}

int main( void ){
* struct some_struct a_struct= { 42 };
* int (*function_pointer)(void*)= & some_function;

This initialisation requires a diagnostic but it is
perfectly OK if you supply a cast (and I prefer to
have no & operator):
int (*function_pointer)(void*)= (int (*)(void *))some_function;

* return (*function_pointer)( & a_struct );

Since some_function is not variadic, better is...

int (*function_pointer)() = some_function;
Yes, that's neater (and I had forgotten you could still do this in
"modern" C).

I was also pleasantly surprised to find that the compiler is obliged
to diagnose the situation where the default argument promotions could
result in a problem at call time; since in such cases the types are no
longer compatible. This is (I flatter myself) a subtle point that had
passed me by.

This means that it is not just that some_function is not variadic that
makes the initialisation valid. As you mentioned in another post, it
is the fact that the declared arguments to some_function are not
altered by the default argument promotions.

For those as slow on the uptake as myself, I believe that if
some_function is declared:

int some_function(float);

the compiler must diagnose a constraint violation, but if it were
declared

int some_function(double);

the initialisation is from a compatible type. This makes your form
more type-safe (within the limits that C permits) than my version with
the explicit casts. There is no way that C can properly type-check
the final call (given that we have now lost the original function
type) but at least it can check for a subtle incompatibility that
could otherwise slip by.

Thank you for pointing this out.

<snip>
--
Ben.
Oct 28 '08 #6

This discussion thread is closed

Replies have been disabled for this discussion.