Functions with Variable Argument ListsĀ
Functions that require variable lists are declared using the ellipsis (...) in the argument list, as described in Variable Argument Lists. To access arguments passed to functions using this method, use the types and macros described in the STDARG.H standard include file in the CRT. For more information on 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, along with the va_list type (declared in STDARG.H), work together:
// 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 list
// of n arguments, where n == strlen( szTypes ).
void ShowVar( char *szTypes, ... ) {
va_list vl;
int i;
// szTypes is the last argument specified; all
// others must be accessed 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 );
}
Output
32.400002 a Test string 4
Comments
The preceding example illustrates these important concepts:
A list marker must be established as a variable of type va_list before any variable arguments are accessed. In the preceding example, the marker is called
vl
.The individual arguments are accessed using the va_arg macro. The va_arg macro needs to be told the type of argument to retrieve so it can transfer the correct number of bytes from the stack. If an incorrect type of a size different than that supplied by the calling program is specified to va_arg, the results are unpredictable.
The result obtained using the va_arg macro should be explicitly cast to the desired type.
The va_end macro must be called to terminate variable-argument processing.