Variadic Functions (stdarg.h)
A variadic function accepts a variable number of arguments — you don't fix the count when you write the function. You've been calling one all along: printf(const char *format, ...) can take one argument or a dozen, depending on how many format specifiers are in the format string. C lets you write your own variadic functions using the macros in <stdarg.h>.
Declaring a variadic function
A variadic function needs at least one fixed, named parameter, and its parameter list ends with an ellipsis ... marking "zero or more additional arguments follow." The fixed parameter conventionally tells the function how many extra arguments to expect, or what format they're in:
int sum(int count, ...); /* count tells sum() how many ints follow */
The stdarg.h macros
Macro | Purpose |
|---|---|
| A type used to declare a variable that tracks your position in the argument list |
| Initializes the |
| Retrieves the next argument, interpreted as |
| Cleans up the |
Worked example: a variadic sum() function
#include <stdio.h>
#include <stdarg.h>
int sum(int count, ...) {
va_list args;
int total = 0;
va_start(args, count); /* start reading right after "count" */
for (int i = 0; i < count; i++) {
total += va_arg(args, int); /* read the next int, advance */
}
va_end(args); /* required cleanup */
return total;
}
int main(void) {
printf("%d\n", sum(3, 10, 20, 30)); /* 60 */
printf("%d\n", sum(5, 1, 2, 3, 4, 5)); /* 15 */
printf("%d\n", sum(0)); /* 0 -- no extra arguments at all */
return 0;
}60 15 0
How the function knows when to stop
Notice that sum relies entirely on the count parameter to know how many arguments follow — there's no way to ask "how many variadic arguments were actually passed?" at runtime. This is exactly why printf counts its format specifiers (%d, %s, and so on) to know how many extra arguments to pull off the list: the format string plays the same role that count plays in sum.
A sentinel value can also mark the end, e.g. a
NULL-terminated list ofchar *arguments.Whatever convention you choose, it is entirely your responsibility to pass matching information — the compiler cannot check it for you.