passing var args as-is to a function

Discussion in 'C Programming' started by sinbad, Mar 25, 2013.

  1. sinbad

    sinbad Guest

    i have a common function which takes variable parameters as an argument,
    depending on the type (the first arg) i want to call the appropriate
    function with rest of the param list, is there any way to do this or
    any better approach. i'm trying to avoid the switch() statement
    below.

    void
    common_func(int type, ...);

    void
    do_one(int x, int y);

    void
    do_two(char a, char b);

    void
    do_any();

    void
    common_func(int type, ...)
    {
    switch(type) {
    case 1;
    do_one(); /* pass 2,3 */
    break;

    case 2:
    do_two(); /* pass 5,6 */
    break;

    default:
    do_any();

    }
    return;
    }

    int main()
    {
    comon_func(1, ,2 ,3);
    comon_func(2, ,5 ,6);
    }
     
    sinbad, Mar 25, 2013
    #1
    1. Advertising

  2. sinbad

    James Kuyper Guest

    On 03/25/2013 05:44 AM, sinbad wrote:
    > i have a common function which takes variable parameters as an argument,
    > depending on the type (the first arg) i want to call the appropriate
    > function with rest of the param list, is there any way to do this or
    > any better approach. i'm trying to avoid the switch() statement
    > below.


    It would help to know why you want to avoid the switch() statement.
    Every alternative I can think of to the switch statement is just a
    different way of implementing a switch (such as if(type==1) {} else
    if(type==2) {} else {}). They don't save you any significant amount of
    typing, and they won't significantly affect how fast the program will
    actually execute. They may make it harder to understand your program,
    because the basic logical structure of any function like this
    corresponds directly to a switch statement, and using other structure to
    achieve the same result would serve only to obscure that fact.

    > void
    > common_func(int type, ...);
    >
    > void
    > do_one(int x, int y);
    >
    > void
    > do_two(char a, char b);


    The promoted type of char is 'int' (unless CHAR_MAX > INT_MAX, an
    unlikely but possible situation, in which case the promoted type would
    be unsigned int). Since the integer promotions are automatically
    performed on the variable portion of the argument list, that makes this
    a bad choice for an example. If these were the only two options, you
    could just define common_func() as taking two additional 'int'
    arguments. Passing a double or a char* would have been a better choice.

    > void
    > do_any();
    >
    > void
    > common_func(int type, ...)
    > {
    > switch(type) {
    > case 1;
    > do_one(); /* pass 2,3 */
    > break;


    You didn't put in any of the stuff needed to actually handle variable
    arguments. Was that just a simplification? Do you know how to use
    <stdarg.h>?

    > case 2:
    > do_two(); /* pass 5,6 */
    > break;
    >
    > default:
    > do_any();
    >
    > }
    > return;
    > }
    >
    > int main()
    > {
    > comon_func(1, ,2 ,3);


    The two commas between 1 and 2 are a syntax error.

    > comon_func(2, ,5 ,6);


    Here, too.

    > }

    --
    James Kuyper
     
    James Kuyper, Mar 25, 2013
    #2
    1. Advertising

  3. Section 7.15 of n1256 describes how to do this. While not the most
    current standard, the information is current and should be adequate
    for your needs. You can download it from
    www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf.

    On Mon, 25 Mar 2013 02:44:24 -0700 (PDT), sinbad
    <> wrote:

    >i have a common function which takes variable parameters as an argument,
    >depending on the type (the first arg) i want to call the appropriate
    >function with rest of the param list, is there any way to do this or
    >any better approach. i'm trying to avoid the switch() statement
    >below.
    >
    >void
    >common_func(int type, ...);
    >
    >void
    >do_one(int x, int y);
    >
    >void
    >do_two(char a, char b);
    >
    >void
    >do_any();
    >
    >void
    >common_func(int type, ...)
    >{
    > switch(type) {
    > case 1;
    > do_one(); /* pass 2,3 */
    > break;
    >
    > case 2:
    > do_two(); /* pass 5,6 */
    > break;
    >
    > default:
    > do_any();
    >
    > }
    > return;
    >}
    >
    >int main()
    >{
    > comon_func(1, ,2 ,3);
    > comon_func(2, ,5 ,6);
    >}


    --
    Remove del for email
     
    Barry Schwarz, Mar 25, 2013
    #3
  4. sinbad

    Paul N Guest

    On Mar 25, 9:44 am, sinbad <> wrote:
    > i have a common function which takes variable parameters as an argument,
    > depending on the type (the first arg) i want to call the appropriate
    > function with rest of the param list, is there any way to do this or
    > any better approach. i'm trying to avoid the switch() statement
    > below.
    >
    > void
    > common_func(int type, ...);
    >
    > void
    > do_one(int x, int y);
    >
    > void
    > do_two(char a, char b);
    >
    > void
    > do_any();
    >
    > void
    > common_func(int type, ...)
    > {
    >     switch(type) {
    >         case 1;
    >         do_one(); /* pass 2,3 */
    >         break;
    >
    >     case 2:
    >         do_two(); /* pass 5,6 */
    >         break;
    >
    >     default:
    >         do_any();
    >
    >     }
    >     return;
    >
    > }
    >
    > int main()
    > {
    >     comon_func(1, ,2 ,3);
    >     comon_func(2, ,5 ,6);
    > }


    I think you haven't really thought through what you want. There are
    times when you want a different function to be called dependent on a
    value that you only know at run-time. This can be done using a switch,
    or by a function pointer, amongst other possibilities.

    However, here you seem to be wanting to call your common function with
    different types or numbers of arguments. At the point of the call, you
    have to specify the arguments, and so you apparently know at compile
    time what the value of "type" is. So why not just call the function
    that you want?

    Hope this helps.
    Paul.
     
    Paul N, Mar 25, 2013
    #4
  5. sinbad

    sinbad Guest

    On Tuesday, March 26, 2013 2:05:25 AM UTC+5:30, Paul N wrote:
    > On Mar 25, 9:44 am, sinbad <> wrote:
    >
    > > i have a common function which takes variable parameters as an argument,

    >
    > > depending on the type (the first arg) i want to call the appropriate

    >
    > > function with rest of the param list, is there any way to do this or

    >
    > > any better approach. i'm trying to avoid the switch() statement

    >
    > > below.

    >
    > >

    >
    > > void

    >
    > > common_func(int type, ...);

    >
    > >

    >
    > > void

    >
    > > do_one(int x, int y);

    >
    > >

    >
    > > void

    >
    > > do_two(char a, char b);

    >
    > >

    >
    > > void

    >
    > > do_any();

    >
    > >

    >
    > > void

    >
    > > common_func(int type, ...)

    >
    > > {

    >
    > >     switch(type) {

    >
    > >         case 1;

    >
    > >         do_one(); /* pass 2,3 */

    >
    > >         break;

    >
    > >

    >
    > >     case 2:

    >
    > >         do_two(); /* pass 5,6 */

    >
    > >         break;

    >
    > >

    >
    > >     default:

    >
    > >         do_any();

    >
    > >

    >
    > >     }

    >
    > >     return;

    >
    > >

    >
    > > }

    >
    > >

    >
    > > int main()

    >
    > > {

    >
    > >     comon_func(1, ,2 ,3);

    >
    > >     comon_func(2, ,5 ,6);

    >
    > > }

    >
    >
    >
    > I think you haven't really thought through what you want. There are
    >
    > times when you want a different function to be called dependent on a
    >
    > value that you only know at run-time. This can be done using a switch,
    >
    > or by a function pointer, amongst other possibilities.
    >
    >
    >
    > However, here you seem to be wanting to call your common function with
    >
    > different types or numbers of arguments. At the point of the call, you
    >
    > have to specify the arguments, and so you apparently know at compile
    >
    > time what the value of "type" is. So why not just call the function
    >
    > that you want?
    >
    >
    >
    > Hope this helps.
    >
    > Paul.


    i have many types, so the switch statement was getting
    very big, i'd like to keep the functions as small as
    possible. The c-standard pointed to Barry helped.
    Thanks Barry. Here's what i want to do, please
    point out any problems.

    #include <stdio.h>
    #include <stdarg.h>

    void
    common_func(int type, ...);

    void
    do_one(va_list ap);

    void
    do_two(va_list ap);

    void
    do_three(va_list ap);

    void
    do_any();

    #define DO_MAX 4
    typedef void (*do_fn)(va_list ap);

    do_fn do_fns[DO_MAX];

    typedef struct new {
    int a;
    char b;
    }new_t;

    void
    do_one(va_list ap)
    {
    int x;
    int y;

    printf("doing one()\n");

    x = va_arg(ap, int);
    y = va_arg(ap, int);

    printf("x is %u y is %u\n", x, y);

    return;
    }

    void
    do_two(va_list ap)
    {
    char a;
    char b;

    printf("doing two()\n");

    a = va_arg(ap, int);
    b = va_arg(ap, int);

    printf("a is %c b is %c\n", a, b);

    return;
    }

    void
    do_three(va_list ap)
    {
    new_t *new;
    char *c;
    int *p;
    void *v;

    printf("doing three()\n");

    c = va_arg(ap, char*);
    p = va_arg(ap, int*);
    v = va_arg(ap, void*);
    new = va_arg(ap, new_t*);

    printf("c is %p\n p is %p\n v is %p\n new is %p\n",
    c, p, v, new );
    return;
    }

    void
    common_func(int type, ...)
    {
    va_list ap;

    va_start(ap, type);

    if ((type > 0) && (type < DO_MAX) && do_fns[type]) {
    do_fns[type](ap);
    }

    va_end(ap);
    return;
    }

    int main()
    {
    new_t *new = (new_t*) 0x2000;
    char *c = (char*) 0x4000;
    int *p = (int*) 0x8000;
    void *v = (void*) 0x9000;

    do_fns[0] = NULL;
    do_fns[1] = do_one;
    do_fns[2] = do_two;
    do_fns[3] = do_three;
    do_fns[DO_MAX] = NULL;

    common_func(1, 2 ,3);
    common_func(2, 'a' ,'b');
    common_func(3, c, p , v, new);

    return(0);
    }
     
    sinbad, Mar 26, 2013
    #5
  6. sinbad

    Paul N Guest

    On Mar 26, 6:28 am, sinbad <> wrote:
    > On Tuesday, March 26, 2013 2:05:25 AM UTC+5:30, Paul N wrote:
    > > On Mar 25, 9:44 am, sinbad <> wrote:

    >
    > > > i have a common function which takes variable parameters as an argument,

    >
    > > > depending on the type (the first arg) i want to call the appropriate

    >
    > > > function with rest of the param list, is there any way to do this or

    >
    > > > any better approach. i'm trying to avoid the switch() statement

    >
    > > > below.

    >
    > > > void

    >
    > > > common_func(int type, ...);

    >
    > > > void

    >
    > > > do_one(int x, int y);

    >
    > > > void

    >
    > > > do_two(char a, char b);

    >
    > > > void

    >
    > > > do_any();

    >
    > > > void

    >
    > > > common_func(int type, ...)

    >
    > > > {

    >
    > > >     switch(type) {

    >
    > > >         case 1;

    >
    > > >         do_one(); /* pass 2,3 */

    >
    > > >         break;

    >
    > > >     case 2:

    >
    > > >         do_two(); /* pass 5,6 */

    >
    > > >         break;

    >
    > > >     default:

    >
    > > >         do_any();

    >
    > > >     }

    >
    > > >     return;

    >
    > > > }

    >
    > > > int main()

    >
    > > > {

    >
    > > >     comon_func(1, ,2 ,3);

    >
    > > >     comon_func(2, ,5 ,6);

    >
    > > > }

    >
    > > I think you haven't really thought through what you want. There are

    >
    > > times when you want a different function to be called dependent on a

    >
    > > value that you only know at run-time. This can be done using a switch,

    >
    > > or by a function pointer, amongst other possibilities.

    >
    > > However, here you seem to be wanting to call your common function with

    >
    > > different types or numbers of arguments. At the point of the call, you

    >
    > > have to specify the arguments, and so you apparently know at compile

    >
    > > time what the value of "type" is. So why not just call the function

    >
    > > that you want?

    >
    > > Hope this helps.

    >
    > > Paul.

    >
    > i have many types, so the switch statement was getting
    > very big, i'd like to keep the functions as small as
    > possible. The c-standard pointed to Barry helped.
    > Thanks Barry. Here's what i want to do, please
    > point out any problems.
    >
    > #include <stdio.h>
    > #include <stdarg.h>
    >
    > void
    > common_func(int type, ...);
    >
    > void
    > do_one(va_list ap);
    >
    > void
    > do_two(va_list ap);
    >
    > void
    > do_three(va_list ap);
    >
    > void
    > do_any();
    >
    > #define DO_MAX 4
    > typedef void (*do_fn)(va_list ap);
    >
    > do_fn do_fns[DO_MAX];
    >
    > typedef struct new  {
    >     int a;
    >     char b;
    >
    > }new_t;
    >
    > void
    > do_one(va_list ap)
    > {
    >     int x;
    >     int y;
    >
    >     printf("doing one()\n");
    >
    >     x = va_arg(ap, int);
    >     y = va_arg(ap, int);
    >
    >     printf("x is %u y is %u\n", x, y);
    >
    >     return;
    >
    > }
    >
    > void
    > do_two(va_list ap)
    > {
    >     char a;
    >     char b;
    >
    >     printf("doing two()\n");
    >
    >     a = va_arg(ap, int);
    >     b = va_arg(ap, int);
    >
    >     printf("a is %c b is %c\n", a, b);
    >
    >     return;
    >
    > }
    >
    > void
    > do_three(va_list ap)
    > {
    >     new_t *new;
    >     char  *c;
    >     int   *p;
    >     void  *v;
    >
    >     printf("doing three()\n");
    >
    >     c   = va_arg(ap, char*);
    >     p   = va_arg(ap, int*);
    >     v   = va_arg(ap, void*);
    >     new = va_arg(ap, new_t*);
    >
    >     printf("c is %p\n p is %p\n v is %p\n new is %p\n",
    >            c, p, v, new );
    >     return;
    >
    > }
    >
    > void
    > common_func(int type, ...)
    > {
    >     va_list ap;
    >
    >     va_start(ap, type);
    >
    >     if ((type > 0) && (type < DO_MAX) && do_fns[type]) {
    >         do_fns[type](ap);
    >     }
    >
    >     va_end(ap);
    >     return;
    >
    > }
    >
    > int main()
    > {
    >     new_t *new = (new_t*) 0x2000;
    >     char  *c   = (char*)  0x4000;
    >     int   *p   = (int*)   0x8000;
    >     void  *v   = (void*)  0x9000;
    >
    >     do_fns[0]      = NULL;
    >     do_fns[1]      = do_one;
    >     do_fns[2]      = do_two;
    >     do_fns[3]      = do_three;
    >     do_fns[DO_MAX] = NULL;
    >
    >     common_func(1, 2 ,3);
    >     common_func(2, 'a' ,'b');
    >     common_func(3, c, p , v, new);
    >
    >     return(0);
    >
    >
    >
    > }


    I haven't checked in detail, but at a quick glance, yes that looks
    right and is what you were asking for.

    It's still a mystery to me why you need to make all the calls through
    the same function "common_func", since your program apparently knows
    which function it wants to call. I was just suggesting that you
    consider whether this is actually required.
     
    Paul N, Mar 26, 2013
    #6
  7. sinbad

    sinbad Guest

    Paul,

    the common_func() does some more functionality which
    is common to all the do_ functions, and it also allows
    me to browse through all the instances where the do_
    funcrtionality is invoked, meaning it's easy to browse
    the code to check where all it is called, that is one
    more reason why i want to use common_func.

    -sinbad
     
    sinbad, Mar 28, 2013
    #7
  8. sinbad

    Mark Bluemel Guest

    On 28/03/2013 08:03, sinbad wrote:
    > Paul,
    >
    > the common_func() does some more functionality which
    > is common to all the do_ functions,


    So split the common functionality out and call it from all the do_
    functions.

    and it also allows
    > me to browse through all the instances where the do_
    > funcrtionality is invoked, meaning it's easy to browse
    > the code to check where all it is called, that is one
    > more reason why i want to use common_func.


    Which, being translated, means "I am going to artificially structure my
    code to suit some spurious measure of programmer convenience, rather
    than structure it based on function".

    Hint: http://en.wikipedia.org/wiki/Ctags
     
    Mark Bluemel, Mar 28, 2013
    #8
  9. On Thu, 28 Mar 2013 09:05:20 -0400, Richard Damon
    <> wrote:

    >On 3/28/13 4:03 AM, sinbad wrote:
    >> Paul,
    >>
    >> the common_func() does some more functionality which
    >> is common to all the do_ functions, and it also allows
    >> me to browse through all the instances where the do_
    >> funcrtionality is invoked, meaning it's easy to browse
    >> the code to check where all it is called, that is one
    >> more reason why i want to use common_func.
    >>
    >> -sinbad
    >>

    >
    >The problem is fundamental. The C language does not provide a method to
    >pass the ... arguments to another function as arguments.


    Sure it does. In C99, it is in paragraph 7.15 of n1256

    --
    Remove del for email
     
    Barry Schwarz, Mar 29, 2013
    #9
    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. Ken Varn
    Replies:
    2
    Views:
    657
    Ken Varn
    Jun 22, 2005
  2. Replies:
    3
    Views:
    536
    David Eppstein
    Sep 17, 2003
  3. Pierre Fortin

    args v. *args passed to: os.path.join()

    Pierre Fortin, Sep 18, 2004, in forum: Python
    Replies:
    2
    Views:
    747
    Pierre Fortin
    Sep 18, 2004
  4. er
    Replies:
    2
    Views:
    541
  5. prati
    Replies:
    0
    Views:
    501
    prati
    Oct 27, 2012
Loading...

Share This Page