Tanner Firl
Tanner Firl

Reputation: 100

With known number of args, forward variadic function in c

I am aware it is generally not possible to forward variadic arguments from one variadic function to another: Forward an invocation of a variadic function in C http://c-faq.com/varargs/handoff.html

My question is, is it possible if I know the number of variadic args in the callee? For example, can f_wrapper be written to pass ... arguments to f?:

int f_wrapper(int argc, ...){ 
  /* argc is the number of variadic args f_wrapper is called with. Can it be used to call f? */
  /* Example: f_wrapper(3, "arg1", "arg2", "arg3"); */
}
int f(...){
  /* f must be called with all ... args from f_wrapper. */
  /* Adding signature with va_list is NOT allowed. c++ is NOT allowed */
}

Upvotes: 2

Views: 108

Answers (1)

John Bollinger
John Bollinger

Reputation: 180058

My question is, is it possible if I know the number of variadic args in the callee? For example, can f_wrapper be written to pass ... arguments to f?

The basic problem is that forwarding variadic arguments from one variadic function to another is a lexical issue, not a data processing issue. You must write a call to the wrapped function in which there is a compile-time representation of each argument, but you don't know until run time how many there will be, and you might not know their types.

If the space of acceptable argument lists is constrained enough, then the problem is pragmatically solvable. For example, if the wrapper will permit only a small number of variadic arguments, of only a small number of types (that it knows how to recognize), then it can analyze the variadic arguments at runtime to match them to the appropriate one of a list of possible calls to the wrapped function. Something like this:

int f_wrapper(int argc, ...) {
    if (argc < 0 || argc > F_ARGS_MAX) {
        // unsupported number of arguments
        return -1;
    }

    int arg_values[F_ARGS_MAX];
    // ... read argc variadic arguments into arg_values ...

    switch (argc) {
        case 0:
            return f();
        case 1:
            return f(arg_values[0]);
        // ...
    }
}

Obviously, however, that gets impractical rather quickly, and it can't cope at all if there is no upper bound on the acceptable number of arguments.

As was suggested in comments, a variadic macro may be a more viable alternative, but that's not a complete substitute. For example, you cannot construct a pointer to a macro, you cannot use such a macro to provide an external interface to a function with internal linkage, the macro cannot host a static variable in the same way that a function does, ....

Upvotes: 3

Related Questions