call a function via a function pointer of different type

Discussion in 'C Programming' started by viza, Oct 26, 2008.

  1. viza

    viza Guest

    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
    viza, Oct 26, 2008
    #1
    1. Advertising

  2. viza <> writes:

    > 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.
    Ben Bacarisse, Oct 26, 2008
    #2
    1. Advertising

  3. viza <> wrote:
    > 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
    Peter Nilsson, Oct 27, 2008
    #3
  4. Ben Bacarisse <> wrote:
    > viza <> writes:
    > > 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
    Peter Nilsson, Oct 28, 2008
    #4
  5. Peter Nilsson <> writes:

    > Ben Bacarisse <> wrote:
    >> viza <> writes:
    >> > 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.
    Ben Bacarisse, Oct 28, 2008
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. lovecreatesbeauty

    Why (type*)pointer isn't equal to *(type**)pointer?

    lovecreatesbeauty, Jan 14, 2006, in forum: C Programming
    Replies:
    10
    Views:
    492
    Peter Shaggy Haywood
    Jan 17, 2006
  2. ais523
    Replies:
    6
    Views:
    307
    Richard G. Riley
    Apr 16, 2006
  3. Felix Kater
    Replies:
    11
    Views:
    483
    Martin Golding
    Jan 12, 2007
  4. Replies:
    5
    Views:
    552
    Thomas J. Gritzan
    Oct 6, 2006
  5. F. Da Costa
    Replies:
    0
    Views:
    147
    F. Da Costa
    Feb 2, 2004
Loading...

Share This Page