call a function via a function pointer of different type

V

viza

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
 
B

Ben Bacarisse

viza said:
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).
 
P

Peter Nilsson

viza said:
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 );
 
P

Peter Nilsson

Ben Bacarisse said:
No!  You can do it but not like this.


This initialisation requires a diagnostic but it is
perfectly OK if you supply a cast (and I prefer to
have no & operator):

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);
 
B

Ben Bacarisse

Peter Nilsson said:
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>
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top