Thread: function with variable function arguments

  1. #1
    Registered User
    Join Date
    Dec 2011
    Posts
    4

    function with variable function arguments

    Hi all!
    I need a function that take a number of pointer to function arguments defined by its first argument.
    I usually solve the problem with a single (or a fixed number of) argument using something like this:
    Code:
    ...
    float f(float x);
    void ex( float (*f)(float x) );
    My problem arise when i want to have the first argument of ex to be number of float function arguments that ex have to accept: how can i tell to va_arg the type of an argument of this sort?

  2. #2
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Code:
    void ex ( int numArgs, ... );
    Called like
    Code:
    ex( 3, f1, f2, f3 );
    The usual stdarg.h examples should be enough from here on in.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Registered User
    Join Date
    Dec 2011
    Posts
    4
    actually i know about the functions in stdarg.h (otherwise i couldn't have known about va_arg). My problem is that i have to tell to va_arg the type of the argument, but i don't know the syntax to refer to a "pointer to function that takes float and return float" type without specifying the name of a variable. I tried something like
    Code:
    va_arg(whatever, float (*)(float) )
    but obviously this doesn't work
    EDIT: i think i figured out a way using typedef, but i would like to know if there is a direct way...

  5. #5
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    EDIT: i think i figured out a way using typedef, but i would like to know if there is a direct way...
    No, the typedef is required. Many compilers will work with the example va_arg call you showed (and if I didn't know better I would expect it to work, too). However, it is invalid according to the standard:

    From C99 7.15.1.1:
    Code:
    type va_arg(va_list ap, type);
    [...]
    The parameter type shall be a type name specified such that the type of a pointer to an object that has the specified type can be obtained simply by postfixing a * to type.

    To get a pointer to a function pointer you've got to stick the * in the middle of the declaration, not at the end. Thus your only option is a typedef.

  6. #6
    Registered User
    Join Date
    Dec 2011
    Posts
    4
    Thanks for the answers.
    I tried again the code that i posted abode... apparently i was wrong, as it compile and works; i didn't effectively runned the program before with that syntax becouse i received a "syntax error"... and strangely the syntax error remains, but the code is compiled anyway. Probably one of those cases where the code is not strictly correct (i.e. doesn't stick to the standard) but is compiled anyway?

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Dunno - I tried something like it as well, and it compiles with MinGW.
    Code:
    #include <stdio.h>
    #include <stdarg.h>
    
    void ex ( int num, ... )
    {
      va_list arguments;
      int x;
      float (*p)(float);
    
      va_start ( arguments, num );
      for ( x = 0; x < num; x++ ) {
        p = (float(*)(float))(va_arg(arguments,void*));
        p = va_arg(arguments, float(*)(float) );
      }
      va_end ( arguments );
    
      return;
    }
    
    int main ( ) {
        return 0;
    }
    I might be tempted to go for the first one anyway. When you pass parameters in the ... positions, ALL type information is lost, and smaller types (short, char, float etc) are promoted to default long types (like int and double).

    Similarly, on machines with variable sized pointers, they would have to be "promoted" to void*, and to extract them from a va_list, you would need to read them as void*, and then cast them back to the correct type.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  8. #8
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    Probably one of those cases where the code is not strictly correct (i.e. doesn't stick to the standard) but is compiled anyway?
    As I said, some compilers will accept it, but it is not standard.

    I have two compilers (tcc and Solaris Studio) that fail to compile it, as is their right. If you want correct code, use the typedef.

  9. #9
    Registered User
    Join Date
    Dec 2011
    Posts
    4
    I use the native gcc compiler on linux, which should be the same of MinGW. Looking better, i figured out that gcc compiles fine the direct syntax, too... the "syntax error" was just the IDE (eclipse).
    Anyway, sticking to the standards, is the
    Code:
    p = (float(*)(float))(va_arg(arguments,void*))
    syntax correct (front the standard point of view i mean)?

  10. #10
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by Kyl View Post
    Thanks for the answers.
    I tried again the code that i posted abode... apparently i was wrong, as it compile and works; i didn't effectively runned the program before with that syntax becouse i received a "syntax error"... and strangely the syntax error remains, but the code is compiled anyway. Probably one of those cases where the code is not strictly correct (i.e. doesn't stick to the standard) but is compiled anyway?
    No, a syntax error means that it could not compile your code. There is no way to run code with a syntax error. What you ran had to have been what was compiled previously.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  11. #11
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    You can't convert a function pointer to void* (it's not guaranteed to work by the standard, is what I mean). Syntactically the code is fine if you properly use casts, but it might not work.

    Use the typedef. That's the correct method. There's no reason to work around it.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Function with variable number of arguments
    By andrewg in forum C Programming
    Replies: 9
    Last Post: 12-18-2010, 09:19 PM
  2. function with variable arguments crashes
    By spongefreddie in forum C Programming
    Replies: 7
    Last Post: 11-18-2010, 03:44 PM
  3. variable number of arguments for a function or a macro
    By mynickmynick in forum C Programming
    Replies: 5
    Last Post: 05-19-2010, 11:35 AM
  4. Variable number of arguments in function.
    By kamoda_pawel in forum C Programming
    Replies: 1
    Last Post: 01-18-2007, 07:18 AM
  5. A function accepting a variable number of arguments.
    By Lithorien in forum C++ Programming
    Replies: 3
    Last Post: 10-10-2004, 01:48 AM