February 16, 2001, 12:00 AM — C provides a special mechanism for defining functions that take a
variable number of arguments. printf() and scanf() are typical examples
of these variadic functions. A variadic function must take at least one
named argument (usually, a format string), but the rest of the
arguments are optional. A special mechanism detects the number of
unnamed arguments and their types, as we will shortly see. A variadic
function is declared as follows:
void printf(const char * fmt,...);
The ellipsis indicates that the function may take any number of
arguments after the mandatory fmt. A variadic function must use C's
default calling convention. A function declared with the "pascal"
calling convention, for instance, cannot take a variable argument list.
Usage
Passing a different number of arguments of different types is
particularly useful in debugging and logging functions. Consider a
debugging function that displays a program's variables to the screen or
writes them to a file; such a function can be used to debug any
application. Normally, you would use printf() for this purpose;
however, because printf() doesn't support user-defined structs and
unions, writing a custom version may be more useful.
Implementation
First, we declare a variadic function that takes a format string and a
variable argument list:
void emit(const char *fmt,...);
For the sake of brevity, the format codes shall be 'd' for double
and 'i' for int. For example:
int ID;
double salary;
/*..*/
emit("is", ID, salary);
The standard header
traversing unnamed arguments. A variable of type va_list will refer to
each argument in turn. This variable is traditionally called ap
("argument pointer"). The second macro, va_start(), initializes ap to
point to the first unnamed argument. va_start() takes ap and the last
named argument of the variadic function:
va_start(ap, fmt); /*make ap point to the first arg after fmt*/
The third macro, va_arg(), takes ap and the current argument's type-
name. It returns the argument and advances ap to the next one (we rely
on the format string to detect the argument list's end). Finally, the
macro va_end(ap) must be called before the function returns to perform
the necessary cleanup.


















