typecasting of function pointers

Discussion in 'C Programming' started by srinivas.satish@gmail.com, Mar 20, 2006.

  1. Guest

    Hi,
    is it possible to typecast a function pointer to two different
    prototypes.
    eg.,
    typedef void (functptr1 *) (int , int);
    typedef void (functptr2 *) (int);
    functptr1 fptr;
    fptr = somefunction_name;
    fptr(10,20);
    fptr = (functptr2)someotherfunction_name;
    (functptr2) fptr(10);

    I tried the above it did'nt work. If this is wrong please let me know
    how it could be done in the right way, also if it is compiler specific,
    which compiler(s) permit this.
    , Mar 20, 2006
    #1
    1. Advertising

  2. Michael Mair Guest

    schrieb:
    > Hi,
    > is it possible to typecast a function pointer to two different
    > prototypes.
    > eg.,
    > typedef void (functptr1 *) (int , int);
    > typedef void (functptr2 *) (int);
    > functptr1 fptr;
    > fptr = somefunction_name;
    > fptr(10,20);
    > fptr = (functptr2)someotherfunction_name;
    > (functptr2) fptr(10);
    >
    > I tried the above it did'nt work. If this is wrong please let me know
    > how it could be done in the right way, also if it is compiler specific,
    > which compiler(s) permit this.


    Please, state exactly what "didn't work" means in future.
    Have a look at
    <http://www.catb.org/~esr/faqs/smart-questions.html>
    And provide the _actual_ code.
    The above cannot compile.

    So, for the language facilities:
    1. Function pointers cannot be converted implicitly (i.e.
    without cast). They cannot be explicitly (i.e. via cast)
    to another function pointer type in a portable, standard
    C way.
    This means: Whenever you cast one function pointer type
    to another, your program becomes inherently non-portable
    and may even break when you use another version of the
    same compiler.
    2. If you have the same return type, you have good chances
    that it will work nonetheless; the right way to do the above
    is
    void foo(int qux, int quux);
    void bar(int baz);

    fptr = foo;
    fptr(10,20);
    fptr = (functptr1) bar;
    ((functptr2)fptr)(10);
    with the typedefs and declarations in place.
    However, you can run into deep trouble if calling the wrong
    type of function with the wrong number of arguments, so this
    is a bad idea at best. If you need different pointer types,
    consider using a union of function pointers and some kind of
    type marker.
    Note: If your parameter list have many parameters (say >5),
    then the chance increases that it will not work.
    3. On many implementations, even casts between function
    pointer types for different return types may work.

    Cheers
    Michael
    --
    E-Mail: Mine is an /at/ gmx /dot/ de address.
    Michael Mair, Mar 20, 2006
    #2
    1. Advertising

  3. Flash Gordon Guest

    Michael Mair wrote:
    > schrieb:
    >> Hi,
    >> is it possible to typecast a function pointer to two different
    >> prototypes.
    >> eg.,
    >> typedef void (functptr1 *) (int , int);
    >> typedef void (functptr2 *) (int);
    >> functptr1 fptr;
    >> fptr = somefunction_name;
    >> fptr(10,20);
    >> fptr = (functptr2)someotherfunction_name;
    >> (functptr2) fptr(10);
    >>
    >> I tried the above it did'nt work. If this is wrong please let me know
    >> how it could be done in the right way, also if it is compiler specific,
    >> which compiler(s) permit this.

    >
    > Please, state exactly what "didn't work" means in future.
    > Have a look at
    > <http://www.catb.org/~esr/faqs/smart-questions.html>
    > And provide the _actual_ code.
    > The above cannot compile.
    >
    > So, for the language facilities:
    > 1. Function pointers cannot be converted implicitly (i.e.
    > without cast). They cannot be explicitly (i.e. via cast)
    > to another function pointer type in a portable, standard
    > C way.
    > This means: Whenever you cast one function pointer type
    > to another, your program becomes inherently non-portable
    > and may even break when you use another version of the
    > same compiler.


    Not completely true. It is perfectly legal to cast from one function
    type to another, it's just that you have to cast it back again before
    calling it. There are even times when this is useful, although not very
    often.

    > 2. If you have the same return type, you have good chances
    > that it will work nonetheless; the right way to do the above
    > is
    > void foo(int qux, int quux);
    > void bar(int baz);
    >
    > fptr = foo;
    > fptr(10,20);
    > fptr = (functptr1) bar;
    > ((functptr2)fptr)(10);
    > with the typedefs and declarations in place.
    > However, you can run into deep trouble if calling the wrong
    > type of function with the wrong number of arguments, so this
    > is a bad idea at best. If you need different pointer types,
    > consider using a union of function pointers and some kind of
    > type marker.
    > Note: If your parameter list have many parameters (say >5),
    > then the chance increases that it will not work.


    I would strongly advise against doing this even if it appears to work.
    If you do not always use all the parameters then there are two simple
    ways to deal with it:
    1) Pass suitable 0 values (or some other place marker) for unused
    parameters.
    2) Write a function that takes a variable number of arguments using the
    mechanism C provides for doing this.

    > 3. On many implementations, even casts between function
    > pointer types for different return types may work.


    However, even if it works you should still not do it.
    --
    Flash Gordon, living in interesting times.
    Web site - http://home.flash-gordon.me.uk/
    comp.lang.c posting guidelines and intro:
    http://clc-wiki.net/wiki/Intro_to_clc
    Flash Gordon, Mar 20, 2006
    #3
  4. Michael Mair Guest

    Flash Gordon schrieb:
    > Michael Mair wrote:
    >> schrieb:
    >>
    >>> Hi,
    >>> is it possible to typecast a function pointer to two different
    >>> prototypes.
    >>> eg.,
    >>> typedef void (functptr1 *) (int , int);
    >>> typedef void (functptr2 *) (int);
    >>> functptr1 fptr;
    >>> fptr = somefunction_name;
    >>> fptr(10,20);
    >>> fptr = (functptr2)someotherfunction_name;
    >>> (functptr2) fptr(10);
    >>>
    >>> I tried the above it did'nt work. If this is wrong please let me know
    >>> how it could be done in the right way, also if it is compiler specific,
    >>> which compiler(s) permit this.

    >>
    >> Please, state exactly what "didn't work" means in future.
    >> Have a look at
    >> <http://www.catb.org/~esr/faqs/smart-questions.html>
    >> And provide the _actual_ code.
    >> The above cannot compile.
    >>
    >> So, for the language facilities:
    >> 1. Function pointers cannot be converted implicitly (i.e.
    >> without cast). They cannot be explicitly (i.e. via cast)
    >> to another function pointer type in a portable, standard
    >> C way.
    >> This means: Whenever you cast one function pointer type
    >> to another, your program becomes inherently non-portable
    >> and may even break when you use another version of the
    >> same compiler.

    >
    > Not completely true. It is perfectly legal to cast from one function
    > type to another, it's just that you have to cast it back again before
    > calling it. There are even times when this is useful, although not very
    > often.


    Thanks for pointing that out.
    For the record: C99, 6.3.2.3#8


    >> 2. If you have the same return type, you have good chances
    >> that it will work nonetheless; the right way to do the above
    >> is
    >> void foo(int qux, int quux);
    >> void bar(int baz);
    >>
    >> fptr = foo;
    >> fptr(10,20);
    >> fptr = (functptr1) bar;
    >> ((functptr2)fptr)(10);
    >> with the typedefs and declarations in place.
    >> However, you can run into deep trouble if calling the wrong
    >> type of function with the wrong number of arguments, so this
    >> is a bad idea at best. If you need different pointer types,
    >> consider using a union of function pointers and some kind of
    >> type marker.
    >> Note: If your parameter list have many parameters (say >5),
    >> then the chance increases that it will not work.

    >
    > I would strongly advise against doing this even if it appears to work.
    > If you do not always use all the parameters then there are two simple
    > ways to deal with it:
    > 1) Pass suitable 0 values (or some other place marker) for unused
    > parameters.
    > 2) Write a function that takes a variable number of arguments using the
    > mechanism C provides for doing this.


    Note: The former may not the natural thing to do; sometimes the
    union-based approach is more helpful. The latter, especially
    with key/value pairs, does not suffer from that but may make for
    troublesome parameter combination checking.

    >> 3. On many implementations, even casts between function
    >> pointer types for different return types may work.

    >
    > However, even if it works you should still not do it.


    Indeed :)


    Cheers
    Michael
    --
    E-Mail: Mine is an /at/ gmx /dot/ de address.
    Michael Mair, Mar 20, 2006
    #4
  5. CBFalconer Guest

    Flash Gordon wrote:
    > Michael Mair wrote:
    >

    .... snip ...
    >
    >> Note: If your parameter list have many parameters (say >5),
    >> then the chance increases that it will not work.

    >
    > I would strongly advise against doing this even if it appears to
    > work. If you do not always use all the parameters then there are
    > two simple ways to deal with it:
    > 1) Pass suitable 0 values (or some other place marker) for
    > unused parameters.
    > 2) Write a function that takes a variable number of arguments
    > using the mechanism C provides for doing this.


    I advise against 2). Variadic functions do not provide proper
    parameter checking, and are the source of many mistakes. They may
    be convenient, but can always be replaced by something.

    --
    "If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers." - Keith Thompson
    More details at: <http://cfaj.freeshell.org/google/>
    Also see <http://www.safalra.com/special/googlegroupsreply/>
    CBFalconer, Mar 20, 2006
    #5
  6. Ben Pfaff Guest

    CBFalconer <> writes:

    > Flash Gordon wrote:
    >> 2) Write a function that takes a variable number of arguments
    >> using the mechanism C provides for doing this.

    >
    > I advise against 2). Variadic functions do not provide proper
    > parameter checking, and are the source of many mistakes. They may
    > be convenient, but can always be replaced by something.


    If you use a compiler that can check variadic function arguments,
    then you gain some protection. For example, GCC can check
    printf()-style variadic function arguments; newer versions can
    also check that an argument list is terminated by a null pointer.
    You don't even have to *always* compile with GCC to get some help
    from this feature; as long as you sometimes compile with GCC, it
    will point out (most of) your mistakes.
    --
    Bite me! said C.
    Ben Pfaff, Mar 21, 2006
    #6
  7. Flash Gordon Guest

    Michael Mair wrote:
    > Flash Gordon schrieb:
    >> Michael Mair wrote:


    <snip stuff agreed>

    >>> 2. If you have the same return type, you have good chances
    >>> that it will work nonetheless; the right way to do the above
    >>> is
    >>> void foo(int qux, int quux);
    >>> void bar(int baz);
    >>>
    >>> fptr = foo;
    >>> fptr(10,20);
    >>> fptr = (functptr1) bar;
    >>> ((functptr2)fptr)(10);
    >>> with the typedefs and declarations in place.
    >>> However, you can run into deep trouble if calling the wrong
    >>> type of function with the wrong number of arguments, so this
    >>> is a bad idea at best. If you need different pointer types,
    >>> consider using a union of function pointers and some kind of
    >>> type marker.
    >>> Note: If your parameter list have many parameters (say >5),
    >>> then the chance increases that it will not work.

    >>
    >> I would strongly advise against doing this even if it appears to work.
    >> If you do not always use all the parameters then there are two simple
    >> ways to deal with it:
    >> 1) Pass suitable 0 values (or some other place marker) for unused
    >> parameters.
    >> 2) Write a function that takes a variable number of arguments using the
    >> mechanism C provides for doing this.

    >
    > Note: The former may not the natural thing to do; sometimes the
    > union-based approach is more helpful. The latter, especially
    > with key/value pairs, does not suffer from that but may make for
    > troublesome parameter combination checking.


    I agree there are many other approaches. I was just pointing out a
    couple of the simplest to implement which don't rely on doing odd stuff
    with function pointers, starting with the very simplest.

    <snip more stuff agreed>
    --
    Flash Gordon, living in interesting times.
    Web site - http://home.flash-gordon.me.uk/
    comp.lang.c posting guidelines and intro:
    http://clc-wiki.net/wiki/Intro_to_clc
    Flash Gordon, Mar 21, 2006
    #7
  8. CBFalconer Guest

    Ben Pfaff wrote:
    > CBFalconer <> writes:
    >> Flash Gordon wrote:

    >
    >>> 2) Write a function that takes a variable number of arguments
    >>> using the mechanism C provides for doing this.

    >>
    >> I advise against 2). Variadic functions do not provide proper
    >> parameter checking, and are the source of many mistakes. They may
    >> be convenient, but can always be replaced by something.

    >
    > If you use a compiler that can check variadic function arguments,
    > then you gain some protection. For example, GCC can check
    > printf()-style variadic function arguments; newer versions can
    > also check that an argument list is terminated by a null pointer.
    > You don't even have to *always* compile with GCC to get some help
    > from this feature; as long as you sometimes compile with GCC, it
    > will point out (most of) your mistakes.


    That's with a constant format string, and for functions that are
    defined in the standard. None of which applies to Flashs suggestion
    2.

    --
    "If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers." - Keith Thompson
    More details at: <http://cfaj.freeshell.org/google/>
    Also see <http://www.safalra.com/special/googlegroupsreply/>
    CBFalconer, Mar 21, 2006
    #8
  9. Ben Pfaff Guest

    CBFalconer <> writes:

    > Ben Pfaff wrote:
    >> For example, GCC can check
    >> printf()-style variadic function arguments; newer versions can
    >> also check that an argument list is terminated by a null pointer.
    >> You don't even have to *always* compile with GCC to get some help
    >> from this feature; as long as you sometimes compile with GCC, it
    >> will point out (most of) your mistakes.

    >
    > That's with a constant format string, and for functions that are
    > defined in the standard.


    You are wrong about the latter: you can apply these to any
    function to you like, using a GCC extension. And, as I said, you
    get most of the benefit even if you don't always use GCC.

    > None of which applies to Flashs suggestion 2.


    The null sentinel check might work, or it might not.
    --
    "I don't have C&V for that handy, but I've got Dan Pop."
    --E. Gibbons
    Ben Pfaff, Mar 21, 2006
    #9
  10. Jordan Abel Guest

    On 2006-03-21, CBFalconer <> wrote:
    > Ben Pfaff wrote:
    >> CBFalconer <> writes:
    >>> Flash Gordon wrote:

    >>
    >>>> 2) Write a function that takes a variable number of arguments
    >>>> using the mechanism C provides for doing this.
    >>>
    >>> I advise against 2). Variadic functions do not provide proper
    >>> parameter checking, and are the source of many mistakes. They may
    >>> be convenient, but can always be replaced by something.

    >>
    >> If you use a compiler that can check variadic function arguments,
    >> then you gain some protection. For example, GCC can check
    >> printf()-style variadic function arguments; newer versions can
    >> also check that an argument list is terminated by a null pointer.
    >> You don't even have to *always* compile with GCC to get some help
    >> from this feature; as long as you sometimes compile with GCC, it
    >> will point out (most of) your mistakes.

    >
    > That's with a constant format string, and for functions that are
    > defined in the standard. None of which applies to Flashs suggestion
    > 2.


    Or, via __attribute__'s, for a format string returned by a function
    guaranteed to return a format string equivalent to its argument, and for
    any function which accepts printf-like or scanf-like format strings.
    Jordan Abel, Mar 21, 2006
    #10
  11. Michael Mair Guest

    CBFalconer schrieb:
    > Flash Gordon wrote:
    >>Michael Mair wrote:

    >
    > ... snip ...
    >
    >>>Note: If your parameter list have many parameters (say >5),
    >>>then the chance increases that it will not work.

    >>
    >>I would strongly advise against doing this even if it appears to
    >>work. If you do not always use all the parameters then there are
    >>two simple ways to deal with it:
    >>1) Pass suitable 0 values (or some other place marker) for
    >> unused parameters.
    >>2) Write a function that takes a variable number of arguments
    >> using the mechanism C provides for doing this.

    >
    > I advise against 2). Variadic functions do not provide proper
    > parameter checking, and are the source of many mistakes. They may
    > be convenient, but can always be replaced by something.


    True; sometimes, this something is so inconvenient that people
    have more trouble getting that right or find it too tedious --
    especially on extension.
    Imagine a function which took a structure until V1.3 -- and then
    the facilities have been dramatically extended for V2.0.
    Now, initializing 20 of 25 struct members to default for the five
    members that matter for the respective application can be very
    ugly. The "tag list" concept, i.e. passing key-value pairs was
    easier on the eye and made for easier checking than the extended
    structure.
    As there was no clear distinction between often used and seldom
    used members (depending on the users), passing several structures
    was quite out of the question, too.
    If the whole thing had been designed with the extended feature
    set in mind, then there would have been better ways than the
    variadic function.
    As mentioned in my reply to Flash Gordon: The true pain then
    happens internally, if there are no longer consistent default
    values and the passed key-value pairs have to be checked for
    consistency.

    This is a corner case which I have seen at least once; in general,
    I agree with the notion to restrict the use of variadic functions
    to the ones that come with the standard library (and not all of
    them).


    Cheers
    Michael
    --
    E-Mail: Mine is an /at/ gmx /dot/ de address.
    Michael Mair, Mar 21, 2006
    #11
  12. Guest

    Hi,
    thanks for all the information
    , Mar 21, 2006
    #12
  13. Flash Gordon Guest

    CBFalconer wrote:
    > Flash Gordon wrote:
    >> Michael Mair wrote:
    >>

    > ... snip ...
    >>> Note: If your parameter list have many parameters (say >5),
    >>> then the chance increases that it will not work.

    >> I would strongly advise against doing this even if it appears to
    >> work. If you do not always use all the parameters then there are
    >> two simple ways to deal with it:
    >> 1) Pass suitable 0 values (or some other place marker) for
    >> unused parameters.
    >> 2) Write a function that takes a variable number of arguments
    >> using the mechanism C provides for doing this.

    >
    > I advise against 2). Variadic functions do not provide proper
    > parameter checking, and are the source of many mistakes. They may
    > be convenient, but can always be replaced by something.


    I'm no fan of variadic functions either, but they are still better than
    casting a function pointer to a type that takes fewer arguments as shown
    in the argument that started this thread.

    My personal preference is for keeping the number of arguments small and
    using suggestion 1, which is why it was my first suggestion.
    --
    Flash Gordon, living in interesting times.
    Web site - http://home.flash-gordon.me.uk/
    comp.lang.c posting guidelines and intro:
    http://clc-wiki.net/wiki/Intro_to_clc
    Flash Gordon, Mar 21, 2006
    #13
    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. brian

    Typecasting Pointers

    brian, Nov 23, 2004, in forum: C Programming
    Replies:
    13
    Views:
    1,271
    Michael Wojcik
    Nov 29, 2004
  2. Replies:
    3
    Views:
    590
    Emmanuel Delahaye
    Jul 15, 2005
  3. Replies:
    12
    Views:
    597
    Stephen Sprunk
    Aug 8, 2006
  4. Nishu

    Typecasting pointers

    Nishu, Jan 29, 2007, in forum: C Programming
    Replies:
    26
    Views:
    1,353
    Bernhard Holzmayer
    Jan 30, 2007
  5. Quentin Pope

    Typecasting Pointers on a 64 bit System

    Quentin Pope, Nov 10, 2011, in forum: C Programming
    Replies:
    54
    Views:
    1,522
    Phil Carmody
    Nov 18, 2011
Loading...

Share This Page