1

Given I have the function:

void A::IAmCool(int x, ...)
{
        va_list args; 
        va_start (args, x);   
        va_end (args);
}

How do I pass var-args from one function to another? I'm looking for something like this:

void A::extractedFunction() /* this doesn't work */
{
        va_list args; 
        va_start (args, ?????);   
        va_end (args);
}

void A::IAmCool(int x, ...)
{
        extractedFunction();
}

Is this even possible? I have tried making the function inline but that doesn't work.

11
  • 2
    I don't know what "extract" means here. Like, at all. Commented May 25, 2012 at 20:52
  • @djechlin: I'm going to guess is referring to the Eclipse-style refactoring facility. Commented May 25, 2012 at 20:53
  • this might help: en.wikipedia.org/wiki/Code_refactoring Commented May 25, 2012 at 20:54
  • 1
    can you not just pass the va_list? Commented May 25, 2012 at 20:57
  • 2
    If you are using C++, do not write variadic functions. End of story. Variadic functions completely lack type safety. There are other patterns (e.g., what the IO streams or Boost Format do) that are far superior. [If you have a compiler with variadic templates support, then that's a different matter altogether, but you've said that you're using Visual C++, which does not support variadic templates.] Commented May 25, 2012 at 21:03

2 Answers 2

1

The usual pattern is to implement your main workhorse function taking a valist, and the variadic function only as "decoration". Then you can use the main function directly from third-party call sites. Example:

#include <cstdarg>

int vgizmo(int a, std::va_list ap)
{
    // main implementation here!
}

int gizmo(int a, ...)  // interface function
{
    std::va_list ap;
    va_start(ap, a);
    int r = vgizmo(a, ap);
    va_end(ap);
    return r;
}

void some_other_stuff(bool q, char const * fmt, ...)
{
    std::va_list ap;
    va_start(ap, fmt);

    // ...

    int b = vgizmo(x, ap);   // third parties use vgizmo directly

    // ...

    va_end(ap);
}
Sign up to request clarification or add additional context in comments.

2 Comments

See vprintf() for a widespread example of this approach... on linux, just man vprintf. And one important thing to note is that in spite of looking like a pass-by-value function call, va_arg() is a macro that modifies the va_list. In other words, you can't pass the same va_list into two different functions without a va_end() and another va_start() in between. Also, the linux man page man stdarg is pretty good.
@BrianMcFarland: You can use va_copy to create multiple copies of a given valist.
0

In C-like languages (C, C++, Objective-C etc.) you can't directly pass variadic arguments. However, you may (and if you're developing an external library, or you just want to facilitate the work of reverse engineers you should) supply a non-variadic version of your function, and make the variadic one just wrap it, so that you can pass down as many arguments as needed to your function -- using va_list. Example:

// variadic function
void variadic_func(int nargs, ...)
{
    // just wrap the non-variadic one
    va_list args;
    va_start(args, nargs);
    non_variadic_func(nargs, args);
    va_end(args);
}

// non-variadic function
void non_variadic_func(int nargs, va_list args)
{
    // do what you want with `args'
}

// you can pass down varargs like this:
void outmost_caller_func(int nargs, ...)
{
    // since you can't pass down the `...', you create a va_list argument list
    va_list args;
    va_start(args, nargs);
    // and call the non-variadic version of your function, just like the wrapper
    // would do (anyway, the wrapper is only for convenience...)
    non_variadic_func(nargs, args);
    va_end(args);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.