How can variadic functions like printf find out the number of arguments they got?
The amount of arguments obviously isn\'t passed as a (hidden) parameter (s
The AMD64 System V ABI (Linux, Mac OS X) does pass the number vector (SSE / AVX) varargs in al (the low byte of RAX), unlike any standard IA-32 calling conventions. See also: Why is %eax zeroed before a call to printf?
But only up to 8 (the max number of registers to use). And IIRC, the ABI allows al to be greater than the actual number of XMM/YMM/ZMM args but it must not be less. So it does not in general always tell you the number of FP args; you can't tell how many more than 8, and al is allowed to overcount.
It's only usable for performance reasons, to skip saving unneeded vector registers to the "Register Save Area" mentioned in "3.5.7 Variable Argument Lists". For example GCC makes code that tests al!=0 and then dumps XMM0..7 to the stack or nothing. (Or if the function uses VA_ARG with __m256 anywhere, then YMM0..7.)
On the C level, there are also other techniques besides parsing the format string as mentioned by others. You could also:
pass a sentinel (void *)0 to indicate the last argument like execl does.
You will want to use the sentinel function attribute to help GCC enforce that at compile time: C warning Missing sentinel in function call
pass it as an extra integer argument with the number of varargs
use the format function attribute to help GCC enforce format strings of known types like printf or strftime
Related: How are variable arguments implemented in gcc?