In some [old] implementations, va_start expands to the left bracket { followed by some declaration, and va_end to the right bracket } , which may precede some “finalization”. Morally, they must match. In practice, often, but not always, order does not matter much (but in principle it matters).
In recent GCC, these macros va_start and va_end expanded to invocations __builtin_va_start and __builtin_va_end , so the compiler may take care (possibly in some future version) that they are correctly nested. Cm. . Thus, a “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 may not matter.
Indentation of mine to emphasize that va_start and va_end are nesting
Of course, you need to call va_arg to really get the va_arg arguments (I hope your process does this). stdarg (3) explains what is good (for C code):
Each call to va_start() must correspond to a corresponding call to va_end() in the same function.
Pay attention to the corresponding word (emphasis mine). I believe this means that va_start and va_end really nested (at least in principle).
source share