A
variadic function is C-speak for a function that takes a variable number of arguments. This is different that
C++ function overloading, where multiple functions share a name but handle different parameters. A single variadic function can be called with any parameters.
The most well-known example is probably printf, one of the first functions a C programmer learns. Unlike languages such as Pascal that have special a syntax for I/O with implicit conversions, printf is just a standard C function, albeit a variadic one.
Writing a variadic function is easy. First, you must include the stdarg.h header file. The stdarg.h header replaced the old, K&R vintage header file varargs.h, which should not be used anymore.
This header defines these macros:
- va_list: This is a type that represents the arguments passed to the function. Some standard C functions like vprintf are not variadic, but take a parameter of type va_list.
- va_start: This macro initializes a va_list with the arguments of the current function; it should always be called before using a va_list.
- va_arg: Each time this macro is called, it successively returns the next argument from a va_list. The expected type is passed as the second parameter (and it better be right!).
- va_end: va_end does any cleanup necessary after you are done with the va_list.
- va_copy: va_copy copies the argument list in case you need to traverse it multiple times.
Next, it is good practice to declare a prototype for your function. You must have at least one regular parameter, followed by a comma and three periods, like an ellipsis. And finally, you must use the above macros to access each argument in sequence.
The astute reader might be wondering how to get the number of parameters passed to a variadic function. Unfortunately, there isn't any way, so that information must be passed to the function manually. For example, printf knows how many parameters there are by counting the number of % substitutions in the format string. Other possibilities are to pass in the number as a parameter, or to end the parameter list with a sentinel.
Here is an example of a variadic function that computes the sum of variable number of integers. The list must be terminated by -1.
int sum(int i, ...) {
va_list args;
int sum, n;
sum = i;
va_start(args, i);
while((n = va_arg(args, int)) != -1) {
sum += n;
}
va_end(args);
return sum;
}
It is also common to write variadic functions that wrap
vprintf-family C library calls. Here is the common
eprintf example:
void eprintf(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
}
Like the
goto statement, variadic functions can be useful in some circumstances, but in general should be shunned. Variadic functions are not type-safe, so you can run into all the problems of un-prototyped K&R C. Passing a value of the wrong type is likely to cause havoc.