Functions with Variable Argument Lists
Collapse the table of content
Expand the table of content
The document is archived and information here might be outdated

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.

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

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.

Show:
© 2016 Microsoft