void va_copy(va_list dest, va_list src);
       An obvious implementation would have a va_list be a pointer to the stack frame
       of the variadic function.  In such a setup (by far the most common) there
       seems nothing against an assignment
 
           va_list aq = ap;
 
       Unfortunately, there are also systems that make it an array of pointers (of
       length 1), and there one needs
 
           va_list aq;
           *aq = *ap;
 
       Finally, on systems where arguments are passed in registers, it may be
       necessary for va_start() to allocate memory, store the arguments there, and
       also an indication of which argument is next, so that va_arg() can step
       through the list.  Now va_end() can free the allocated memory again.  To
       accommodate this situation, C99 adds a macro va_copy(), so that the above
       assignment can be replaced by
 
           va_list aq;
           va_copy(aq, ap);
           ...
           va_end(aq);
 
       Each invocation of va_copy() must be matched by a corresponding invocation of
       va_end() in the same function.  Some systems that do not supply va_copy() have
       __va_copy instead, since that was the name used in the draft proposal.
 

The va_start(), va_arg(), and va_end() macros conform to C89. C99 defines the va_copy() macro.