1

Let's consider 2 functions, void fooA(int argc, ...) and void fooB(int argc, ...)

I need to pass the variable arguments I get from fooA to fooB. And except for passing them to fooB, I never need to handle these variable arguments in fooA.

I tried something like changing fooB to void fooB(int argc, void* argv) and pass the arguments like in the following code:

void fooA(int argc, ...)    {
    // Some processing ...
    va_list list;
    va_start(list, argc);
    void **argv = NULL;

    argv = malloc(argc * sizeof(void*));
    for (int i = 0; i < argc; i++)
        argv[i] = va_arg(list, void*);

    fooB(argc, argv);
}

But it's not very clean, and I would like to know if there is a way to do that without even handling the variable arguments in the fooA function.

EDIT: It's not a dupe of this question because in my case I can modify fooA or fooB definition (even if I would not like to). And even if it works great, I can't accept Jonathan Leffler technical because I just can't put a forwarder for each fooB-like function. They are called with a static function pointer array and I need to have all my fooB methods alone in the same C file.

Community
  • 1
  • 1
Antoine C.
  • 3,730
  • 5
  • 32
  • 56
  • This is a duplicate (but finding it will take time). You need a `void vFooB(int argc, va_list args)` that can be called from `fooA()`. In fact, you normally need a `vFooB(int argc, va_list args)` for each `void fooB(int argc, ...)`, and you implement the latter in terms of the former (so `void fooB(int argc, ...) { va_list args; va_start(args, argc); vFooB(argc, args); va_end(args); }` with `vFooB()` doing the real work. – Jonathan Leffler Jun 02 '14 at 18:26
  • I was writing a great answer before the question was closed; this is not a duplicate. – this Jun 02 '14 at 18:32
  • I was hoping to see your great answer. And I can't use Jonathan's technical because of some reasons (mainly because I use a generated function pointers array to call fooB, and because I have some restrictions on the fooB function side). – Antoine C. Jun 02 '14 at 18:34
  • @LoveMetal You can flag the question for moderator attention, if you feel the closure was unjustified. – this Jun 02 '14 at 18:35
  • 2
    @LoveMetal - self is correct about asking for the question to be reopened... but before you do that, you should edit it to address the fact of why Jonathan's answer doesn't work for you, and why it's not a duplicate. Doing a little leg work like that will help keep it open and get you better answers. If it was closed as a duplicate, but you feel your question is unique and not answered by the duplicate question, then you need to make it clearer why that is the case – Mike Jun 02 '14 at 18:38
  • 1
    I'll stand by the close — I'd have done it if dasblinkenlight had not. It seems to be precisely a duplicate. To warrant unduplicating it, the question should at least be updated to indicate what constraints there are on modifying functions — and why — and should note that the correct solution cannot be applied (with a detailed explanation of why the correct solution cannot be used). If there are special circumstances that apply (such as the variadic argument list is more uniform than `...` implies), these should be noted too. – Jonathan Leffler Jun 02 '14 at 18:39
  • 1
    The "duplicate" involved mapping a user variadic to a standard library provided variadic. That is not what is being asked here, and the accepted answer is not as specific to this situation as Jonathan's. If you thought it worth clarification @JonathanLeffler it probably deserved an answer rather than a comment. – Clifford Jun 02 '14 at 18:47
  • Your code should review where the allocated array is freed (and should check for success of allocation). Or you could use `void *argv[argc];` (a VLA -- variable-length array) instead of `malloc()`. The copy loop would be the same. This code assumes that all the types in the variable argument list are pointer types; if they aren't, it may not work as expected. I don't understand why you can't put in a forwarder; your explanation is not clear enough. A forwarder is an internal implementation detail; the external interfaces don't need to change. – Jonathan Leffler Jun 02 '14 at 20:33
  • @this: it's not closed anymore – newacct Jul 17 '14 at 00:58

1 Answers1

0

If you want to handle arguments in the second function then call start and end in the first and retrieve the arguments in the second one.

#include <stdarg.h>

void TestSub( int n , va_list* list )
{
    for( int i = 0 ; i < n ; i++ )
    {
        double d = va_arg( *list , double ) ;
        printf("%lf " , d ) ;
    }

}

void Test( int n , ... )
{
    va_list list ;
    va_start( list,  n ) ;

    TestSub( n , &list ) ;

    va_end( list ) ;
}

You would call the function like this

Test( 3 , 3.14 , ( double )2 , 1234.5678 ) ;

Note that all double arguments must be actually double, if you pass an integer to this variable argument function it will not get converted automatically.

If you intend to pass void pointers to your variable args function, then make sure they are really void* !

this
  • 5,229
  • 1
  • 22
  • 51