Previous Page
Next Page

7.7. Variable Numbers of Arguments

C allows you to define functions that you can call with a variable number of arguments. These are sometimes called variadic functions. Such functions require a fixed number of mandatory arguments, followed by a variable number of optional arguments. Each such function must have at least one mandatory argument. The types of the optional arguments can also vary. The number of optional arguments is either determined by the values of the mandatory arguments , or by a special value that terminates the list of optional arguments.

The best-known examples of variadic functions in C are the standard library functions printf( ) and scanf( ). Each of these two functions has one mandatory argument , the format string. The conversion specifiers in the format string determine the number and the types of the optional arguments.

For each mandatory argument, the function head shows an appropriate parameter, as in ordinary function declarations. These are followed in the parameter list by a comma and an ellipsis (...), which stands for the optional arguments.

Internally, variadic functions access any optional arguments through an object with the type va_list, which contains the argument information. An object of this typealso called an argument pointercontains at least the position of one argument on the stack. The argument pointer can be advanced from one optional argument to the next, allowing a function to work through the list of optional arguments. The type va_list is defined in the header file stdarg.h.

When you write a function with a variable number of arguments, you must define an argument pointer with the type va_list in order to read the optional arguments. In the following description, the va_list object is named argptr. You can manipulate the argument pointer using four macros, which are defined in the header file stdarg.h:

void va_start( va_list argptr, lastparam );

The macro va_start initializes the argument pointer argptr with the position of the first optional argument. The macro's second argument must be the name of the function's last named parameter. You must call this macro before your function can use the optional arguments.

type va_arg( va_list argptr, type );

The macro va_arg expands to yield the optional argument currently referenced by argptr, and also advances argptr to reference the next argument in the list. The second argument of the macro va_arg is the type of the argument being read.

void va_end( va_list argptr );

When you have finished using an argument pointer, you should call the macro va_end. If you want to use one of the macros va_start or va_copy to reinitialize a function pointer that you have already used, then you must call va_end first.

void va_copy( va_list dest, va_list src );

The macro va_copy initializes the argument pointer dest with the current value of src. You can then use the copy in dest to access the list of optional arguments again, starting from the position referenced by src.

The function in Example 7-9 demonstrates the use of these macros.

Example 7-9. Function add( )
// The add( ) function computes the sum of the optional arguments.
// Arguments:    The mandatory first argument indicates the number of
//               optional arguments. The optional arguments are
//               of type double.
// Return value: The sum, with type double.

double add( int n, ... )
  int i = 0;
  double sum = 0.0;
  va_list argptr;
  va_start( argptr, n );              // Initialize argptr;
  for ( i = 0; i < n; ++i )           // that is, for each optional argument,
    sum += va_arg( argptr, double );  // read an argument with type double
                                      // and accumulate in sum.
  va_end( argptr );
  return sum;

Previous Page
Next Page