MOHAMED
MOHAMED

Reputation: 43518

How to add an argument to a va_list

I have the following code:

int __dmasprintf (char **s, const char *format, ...) {

    char buf[512];
    va_list arg;
    int ret;
    va_start(arg,format);
    ret = vsprintf(buf, format, arg);
    va_end(arg);

    *s = strdup(buf);
    if (*s == NULL) return -1;
    return 0;   
}

I want to add an argument to the va_list arg before calling vsprintf() because my format contains 1 extra argument at the end.

How to add an argument (for example char * myarg) to the the va_list arg?

Or is it possible to pass vsprintf() a customized list?

Upvotes: 8

Views: 9476

Answers (2)

Useless
Useless

Reputation: 67713

You can't.

You either need to make two vsprintf (surely vsnprintf?) calls, or replace your function with a variadic macro, like

#define __dmasprintf(S, FMT, ...) ( \
    (*S = do_dmasprintf(FMT, __VA_ARGS__, my_arg)) == NULL ? -1 : 0)

char *do__dmasprintf (const char *format, ...) {

    char buf[512];
    va_list arg;
    int ret;
    va_start(arg,format);
    ret = vsnprintf(buf, sizeof(buf), format, arg);
    va_end(arg);

    char *s = strdup(buf);
    return s;   
}

Notes:

  1. I replaced vsprintf with vsnprintf. There's no reason to use the former here (or pretty much anywhere else)
  2. you ignore ret. Should you?
  3. I kept the macro argument layout similar to the original, but since __VA_ARGS__ must be one-or-more arguments (it can't be empty), that means at least one argument is required after FMT. Just remove the FMT argument entirely if you want to allow zero arguments after it.

Upvotes: 8

Serge Ballesta
Serge Ballesta

Reputation: 148880

There is unfortunately no direct way to do that. There is a reason for that : the stdarg macros take the address in the stack of the last known parameter, and then directly iterate the stack.

If you can use macros, @Useless provided a nice solution - beware, macros can have side effects when you pass variables pre- or post-fixed with ++ or --.

If you want to avoid macros, you will have to write your own variant of vsprintf. No problem for it, just find a source for C stdlib (GNU libc could be a nice start point) and be brave ... hope you can use macros !

Upvotes: 2

Related Questions