va_end
doesn't need to be implemented as a macro, and neither, I think, does va_start (you'd just have to add &
to the parameters to pass a pointer to them). Actually va_end
and va_start
have to be imlemented as macros because you can't use &
in all cases, as was pointed out in the comments.
va_arg
must be implemented as a macro because you need to provide a type as a parameter to it, which you can't do without macros.
va_start
works as you presume: you give it the first argument, and it can calculate based on the size of that argument what position the other arguments are at, because they are all contiguous on the stack.
It simply starts the va_list
pointing at the end of the first argument (which you pass to va_start
) and adds the size of the next one every time you use va_arg
.