In C, variadic functions can take a varying number of arguments. To access the args, <stdarg.h> needs to be included which defines a type va_list and macros va_start, va_arg, va_end, va_copy.

For a function void printf(const char* format, ...), we’ll do the following:

va_list args;
va_start(args, format);
// Process the args using va_arg
va_end(args);

va_start takes a va_list. It shouldn’t be a register variable or array as the macro might take its address. The second variable it takes is the name of the last argument of the function after which the variadic args start.

Each va_start has to be coupled with a call to va_end after which the variable args is undefined. For platforms on which va_start allocates, va_end is needed to perform deallocation.

va_copy

We can use va_start/va_end pair again to iterate over the arguments. However for platforms where va_start allocates it is inefficient. To give a platform agnostic way to iterate again, C99 introduced va_copy.

The behaviour of va_copy is as if va_start was called with it and the same last argument along with the same number of va_arg calls. Basically, it will point to the same argument as the source.

Here’s how we’ll use va_copy:

va_list args, args2;
va_start(args, format);
va_copy(args2);
// Do stuff with args and args2
va_end(args);
va_end(args2);

Note that a call to va_copy needs to be paired with a call to va_end.