# stdarg.h **`stdarg.h`** provides the machinery for writing variadic functions — functions that accept a variable number of arguments, like `printf`. Without it you would have no portable way to iterate over the unnamed arguments. It defines `va_list`, and the `va_start`, `va_arg`, `va_end`, and `va_copy` macros. ```c #include #include int sum(int count, ...) { va_list ap; va_start(ap, count); // initialise: 'count' is the last named param int total = 0; for (int i = 0; i < count; i++) total += va_arg(ap, int); // pull the next argument as int va_end(ap); // mandatory cleanup return total; } // sum(4, 10, 20, 30, 40) → 100 ``` `va_start(ap, last)` initialises the list starting just after `last` (the final named parameter). `va_arg(ap, type)` reads the next argument and advances the cursor. `va_end(ap)` must be called before the function returns. `va_copy(dst, src)` copies a `va_list` so you can traverse the arguments twice — useful when you call `vsnprintf` once to measure the required buffer length and again to fill it. There is no type safety: `va_arg` trusts the type you give it. If the caller passed a `double` but you read it as `int`, you get undefined behaviour and likely garbage. `printf` encodes expected types in the format string; other variadic APIs use a sentinel value or an explicit count argument as the contract. ## Practice ```c // compile: gcc -o vademo vademo.c // run: ./vademo // description: variadic minimum function using va_list #include #include #include int vmin(int count, ...) { va_list ap; va_start(ap, count); int m = INT_MAX; for (int i = 0; i < count; i++) { int v = va_arg(ap, int); if (v < m) m = v; } va_end(ap); return m; } int main(void) { printf("min(3, 7, 1, 9) = %d\n", vmin(4, 3, 7, 1, 9)); printf("min(42) = %d\n", vmin(1, 42)); printf("min(empty) = %d\n", vmin(0)); // INT_MAX — no args return 0; } ``` Try passing a `double` where an `int` is expected by adding `vmin(1, 3.14)`. On most platforms you will get a garbage result rather than a crash — that is the risk of variadic functions without runtime type checking. The count-based approach here is one way to bound the iteration; the other common approach is a NULL sentinel at the end of the argument list.