A variadic function accepts a variable number of arguments by placing an ellipsis (...) after its known parameters. Calls provide the initial arguments, such as printf’s format, followed by any number of additional values. section 16.5
The interface is difficult because the compiler cannot determine the expected type of each variadic argument. Arithmetic arguments undergo the usual promotions, except float becomes double; char and short commonly become int. The called function still needs valid type information for every value. section 16.5.2
Reading a counted list
double sumIt(size_t n, ...) { double ret = 0.0; va_list va; va_start(va, n); for (size_t i = 0; i < n; ++i) ret += va_arg(va, double); va_end(va); return ret; } Here, n states how many additional arguments follow. va_start initializes traversal, va_arg reads each value as double, and va_end finishes it. The caller must pass values compatible with those expectations.
Format-directed interpretation
printf("%hhu", zChar); zChar is promoted to int before the call; printf uses %hhu to interpret the received value as unsigned char. Format specifications therefore carry type information outside the function’s parameter list. section 16.5.2
20 FILE* iodebug = 0;
21
22 /**
23 ** @brief Prints to the debug stream @c iodebug
24 **/
25 #ifdef __GNUC__
26 __attribute__((format(printf, 1, 2)))
27 #endif
28 int printf_debug(const char *format, ...) {
29 int ret = 0;
30 if (iodebug) {
31 va_list va;
32 va_start(va, format);
33 ret = vfprintf(iodebug, format, va);
34 va_end(va);
35 }
36 return ret;
37 }
!@%STYLE%@!
{"css":"{\"css\": \"font-weight: bold;\"}","target":"[[{\"line\":0,\"ch\":0},{\"line\":0,\"ch\":2}],[{\"line\":0,\"ch\":5},{\"line\":0,\"ch\":9}],[{\"line\":1,\"ch\":0},{\"line\":1,\"ch\":2}],[{\"line\":2,\"ch\":0},{\"line\":2,\"ch\":2}],[{\"line\":3,\"ch\":0},{\"line\":3,\"ch\":2}],[{\"line\":4,\"ch\":0},{\"line\":4,\"ch\":2}],[{\"line\":5,\"ch\":0},{\"line\":5,\"ch\":2}],[{\"line\":5,\"ch\":5},{\"line\":5,\"ch\":11}],[{\"line\":6,\"ch\":0},{\"line\":6,\"ch\":2}],[{\"line\":6,\"ch\":27},{\"line\":6,\"ch\":33}],[{\"line\":8,\"ch\":9},{\"line\":8,\"ch\":15}],[{\"line\":13,\"ch\":17},{\"line\":13,\"ch\":23}],[{\"line\":7,\"ch\":0},{\"line\":7,\"ch\":2}],[{\"line\":7,\"ch\":5},{\"line\":7,\"ch\":11}],[{\"line\":8,\"ch\":0},{\"line\":8,\"ch\":2}],[{\"line\":3,\"ch\":18},{\"line\":3,\"ch\":21}],[{\"line\":6,\"ch\":29},{\"line\":6,\"ch\":32}],[{\"line\":8,\"ch\":5},{\"line\":8,\"ch\":8}],[{\"line\":9,\"ch\":7},{\"line\":9,\"ch\":10}],[{\"line\":13,\"ch\":19},{\"line\":13,\"ch\":22}],[{\"line\":8,\"ch\":22},{\"line\":8,\"ch\":32}],[{\"line\":9,\"ch\":0},{\"line\":9,\"ch\":2}],[{\"line\":3,\"ch\":18},{\"line\":3,\"ch\":21}],[{\"line\":6,\"ch\":29},{\"line\":6,\"ch\":32}],[{\"line\":8,\"ch\":5},{\"line\":8,\"ch\":8}],[{\"line\":9,\"ch\":7},{\"line\":9,\"ch\":10}],[{\"line\":13,\"ch\":19},{\"line\":13,\"ch\":22}],[{\"line\":10,\"ch\":0},{\"line\":10,\"ch\":2}],[{\"line\":5,\"ch\":6},{\"line\":5,\"ch\":8}],[{\"line\":7,\"ch\":9},{\"line\":7,\"ch\":11}],[{\"line\":10,\"ch\":7},{\"line\":10,\"ch\":9}],[{\"line\":11,\"ch\":0},{\"line\":11,\"ch\":2}],[{\"line\":11,\"ch\":9},{\"line\":11,\"ch\":16}],[{\"line\":12,\"ch\":0},{\"line\":12,\"ch\":2}],[{\"line\":12,\"ch\":9},{\"line\":12,\"ch\":17}],[{\"line\":13,\"ch\":0},{\"line\":13,\"ch\":2}],[{\"line\":13,\"ch\":15},{\"line\":13,\"ch\":23}],[{\"line\":14,\"ch\":0},{\"line\":14,\"ch\":2}],[{\"line\":14,\"ch\":9},{\"line\":14,\"ch\":15}],[{\"line\":15,\"ch\":0},{\"line\":15,\"ch\":2}],[{\"line\":16,\"ch\":0},{\"line\":16,\"ch\":2}],[{\"line\":16,\"ch\":7},{\"line\":16,\"ch\":13}],[{\"line\":17,\"ch\":0},{\"line\":17,\"ch\":2}]]"}
!@%STYLE%@!
Shows a debug-printing wrapper that forwards its variadic arguments to vfprintf and brackets traversal with va_start and va_end. section 16.5.2







