Functions with Variable Argument Lists
Functions that require variable lists are declared by using the ellipsis (...) in the argument list, as described in Variable Argument Lists. Use the types and macros that are described in the STDARG.H include file to access arguments that are passed by a variable list. For more information about these macros, see va_arg, va_end, va_start in the documentation for the C Run-Time Library.
Example
The following example shows how the va_start, va_arg, and va_end macros work together with the va_list type (declared in STDARG.H):
// variable_argument_lists.cpp
#include <stdio.h>
#include <stdarg.h>
// Declaration, but not definition, of ShowVar.
void ShowVar( char *szTypes, ... );
int main() {
ShowVar( "fcsi", 32.4f, 'a', "Test string", 4 );
}
// ShowVar takes a format string of the form
// "ifcs", where each character specifies the
// type of the argument in that position.
//
// i = int
// f = float
// c = char
// s = string (char *)
//
// Following the format specification is a variable
// list of arguments. Each argument corresponds to
// a format character in the format string to which
// the szTypes parameter points
void ShowVar( char *szTypes, ... ) {
va_list vl;
int i;
// szTypes is the last argument specified; you must access
// all others using the variable-argument macros.
va_start( vl, szTypes );
// Step through the list.
for( i = 0; szTypes[i] != '\0'; ++i ) {
union Printable_t {
int i;
float f;
char c;
char *s;
} Printable;
switch( szTypes[i] ) { // Type to expect.
case 'i':
Printable.i = va_arg( vl, int );
printf_s( "%i\n", Printable.i );
break;
case 'f':
Printable.f = va_arg( vl, double );
printf_s( "%f\n", Printable.f );
break;
case 'c':
Printable.c = va_arg( vl, char );
printf_s( "%c\n", Printable.c );
break;
case 's':
Printable.s = va_arg( vl, char * );
printf_s( "%s\n", Printable.s );
break;
default:
break;
}
}
va_end( vl );
}
32.400002
a
Test string
4
Comments
The previous example illustrates these important concepts:
You must establish a list marker as a variable of type va_list before any variable arguments are accessed. In the previous example, the marker is called vl.
The individual arguments are accessed by using the va_arg macro. You must tell the va_arg macro the type of argument to retrieve so that it can transfer the correct number of bytes from the stack. If you specify an incorrect type of a size different from that supplied by the calling program to va_arg, the results are unpredictable.
You should explicitly cast the result obtained by using the va_arg macro to the type that you want.
You must call the va_end macro to terminate variable-argument processing.