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.
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:
#include <stdio.h>
#include <stdarg.h>
// Declaration, but not definition, of ShowVar.
int ShowVar( char *szTypes, ... );
main()
{
ShowVar( "fdcsi", 32.4f, 298.34E3, 'a', "Test string", 4 );
return 0;
}
// ShowVar takes a format string of the form
// "ifdcs", where each character specifies the
// type of the argument in that position.
//
// i = int
// f = float
// d = double
// c = char
// s = string (char *)
//
// Following the format specification is a list
// of n arguments, where n == strlen( szTypes ).
int 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;
double d;
char c;
char *s;
} Printable;
switch( szTypes[i] ) // Type to expect.
{
case 'i':
Printable.i = (int)va_arg( vl, int );
printf( "%i\n", Printable.i );
break;
case 'f':
Printable.f = (float)va_arg( vl, float );
printf( "%f\n", Printable.f );
break;
case 'd':
Printable.d = (double)va_arg( vl, double );
printf( "%f\n", Printable.d );
break;
case 'c':
Printable.c = (char)va_arg( vl, char );
printf( "%c\n", Printable.c );
break;
case 's':
Printable.s = (char *)va_arg( vl, char * );
printf( "%s\n", Printable.s );
break;
default:
break;
}
}
va_end( vl );
return 0;
}
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.