I have the following code:
va_list va[2];
va_start(va[0], fmt);
va_start(va[1], fmt);
process(fmt, va);
va_end(va[0]);
va_end(va[1]);
I've looked at various sites for documentation on va_start
and va_end
, and all they say is that va_end
should be invoked for each va_start
before the calling function returns.
What I am unsure about is whether or not the order of the calls is significant. In particular, is
va_end(va[0]);
va_end(va[1]);
sementically identical to
va_end(va[1]);
va_end(va[0]);
in the above sample code?
On some [old] implementations, va_start
expanded to a left brace {
followed by some declaration, and va_end
expanded to a right brace }
possibly preceded by some "finalization". Morally they should match. In practice, often but not always, order does not matter much (but in principle it does matter).
On recent GCC, these va_start
and va_end
macros expand to invocations of __builtin_va_start
& __builtin_va_end
so the compiler may care (perhaps in some future version) that these are correctly nested. See this. So the "good" order should be:
va_list va[2];
va_start(va[0], fmt);
va_start(va[1], fmt);
process(fmt, va);
va_end(va[1]);
va_end(va[0]);
In practice the order of va_end
might not matter that much.
The indentation is mine to emphasize that va_start
& va_end
are "nesting"
Of course, you need to call va_arg
to really retrieve variadic arguments (I hope that your process
is doing that). stdarg(3) explains that well (for C code):
Each invocation of
va_start()
must be matched by a corresponding invocation ofva_end()
in the same function.
Notice the corresponding word (emphasis is mine). I believe it means that va_start
and va_end
are really nesting (at least in principle).