13.14 <cstdarg>

The <cstdarg> header is the C++ version of the C standard <stdarg.h> header, which declares macros for accessing the arguments to a function that takes a variable number of arguments, that is, a function that is declared with an ellipsis as the last parameter.

A function that takes a variable number of arguments (called a variadic function) must have some way of knowing how many arguments have actually been passed to the function and what their types are. For example, the printf function (in <cstdio>) uses its format string to determine the number and type of arguments.

Example 13-8 shows how a function can use the <cstdarg> macros. The max function takes at least two arguments. The first is a count of the number of remaining arguments; the count must be positive. The template parameter specifies the type of each argument that follows the count.

Example 13-8. Finding the maximum value of any number of arguments
#include <cassert>

#include <cstdarg>

   

// Use a trivial wrapper class to ensure that va_end is called.

class varargs {

public:

  ~varargs(  ) { va_end(ap); }

  std::va_list& ap;

};

   

template <typename T>

T max(unsigned count, ...)

{

  assert(count > 0);

  varargs va;

  va_start(va.ap, count);

  T result = va_arg(va.ap, T);  // Get first argument.

  while (--count > 0) {

    T arg = va_arg(va.ap, T);   // Get successive arguments.

    if (arg > result)

      result = arg;             // Remember the largest.

  }

  return result;

}

   

int main(  )

{

  int a, b, c, d;

  ...

  int x = max<int>(4, a, b, c, d);

  int y = max<int>(2, x, 42);

  return y;

}
va_arg macro Gets next argument

T va_arg(va_list ap, T)

The va_arg macro fetches the next argument, which must be of type T. The ap parameter must have been initialized by calling va_start. The type T must be a type that results from the standard type promotions (Chapter 3) or else the behavior is undefined. For example, T cannot be char, but must be int because the standard promotion of type char is to type int (or, in rare circumstances, unsigned int). The behavior is undefined if there is no next argument.

va_end macro Ends getting arguments

void va_end(va_list ap)

The va_end macro finishes fetching arguments. You must call va_end once for each call to va_start. You cannot nest calls to va_start and va_end, but you can call them multiple times sequentially in the same function.

va_list type Argument list

typedef ... va_list;

The va_list type is an opaque type that refers to the function's arguments. Declare a local variable of type va_list and supply the variable to the va_start, va_arg, and va_end macros.

va_start macro Starts getting arguments

void va_start(va_list& ap, lastNamedParm)

The va_start macro initializes ap and prepares to fetch function arguments with va_arg. You must call va_end to clean up and finalize ap. The second argument to va_start is the name of the function's last parameter before the ellipsis. The last named parameter must not have a function, array, or reference type.