3.14. VARIADIC FUNCTIONS
break;
sum=sum+(*i);
count++;
i++;
}
return sum/count;
};
int main()
{
printf ("%d\n", arith_mean (1, 2, 7, 10, 15, -1 / terminator /));
// test: https://www.wolframalpha.com/input/?i=mean(1,2,7,10,15)
};
In other words, if an argument set is array of words (32-bit or 64-bit), we just enumerate array elements
starting at first one.
3.14.2vprintf()function case
Many programmers define their own logging functions which take a printf-like format string + a variable
number of arguments.
Another popular example is the die() function, which prints some message and exits.
We need some way to pack input arguments of unknown number and pass them to theprintf()function.
But how?
That’s why there are functions with “v” in name.
One of them isvprintf(): it takes a format-string and a pointer to a variable of typeva_list:
#include <stdlib.h>
#include <stdarg.h>
void die (const char * fmt, ...)
{
va_list va;
va_start (va, fmt);
vprintf (fmt, va);
exit(0);
};
By closer examination, we can see thatva_listis a pointer to an array. Let’s compile:
Listing 3.60: Optimizing MSVC 2010
_fmt$ = 8
_die PROC
; load 1st argument (format-string)
mov ecx, DWORD PTR _fmt$[esp-4]
; get pointer to the 2nd argument
lea eax, DWORD PTR _fmt$[esp]
push eax ; pass a pointer
push ecx
call _vprintf
add esp, 8
push 0
call _exit
$LN3@die:
int 3
_die ENDP
We see that all our function does is just taking a pointer to the arguments and passing it tovprintf(), and
that function is treating it like an infinite array of arguments!
Listing 3.61: Optimizing MSVC 2012 x64
fmt$ = 48