Names specified for <stdarg.h>, “Variable-length argument lists”
Name Description Notes Source Availability
va_arg() Extract argument L M (·) <stdarg.h> C89 C90 C95 C99 C11
va_copy() Copy argument iterator L M (·) <stdarg.h> C99 C11
va_end() Release argument iterator L M (·) <stdarg.h> C89 C90 C95 C99 C11
va_list Argument iterator L T <stdarg.h> C89 C90 C95 C99 C11
va_start() Initialise argument iterator L M (·) <stdarg.h> C89 C90 C95 C99 C11

This header is available in C89, C90, C95, C99 and C11.

In C, functions can be declared with only a partially specified parameter list, such as the following, which has two specified parameters, followed by an ellipsis:

void func(int a1, double a2, ...);

Calls to this function can then take any of the following forms, for example:

func(10, 20.0);
func(10, 20.0, "fred");
func(10, 20.0, L"fred", 34);
func(10, 20.0, 2.0 + I * 3, 10, 20, 30);
// ad nauseum

The types of the first two arguments can be checked against the types of the first two parameters, but no further translation-time checking can be done on the remaining arguments.

<stdarg.h> defines macros for accessing variable-length argument lists from within a function defined with an ellipsis. It defines a type va_list as an iterator to pass over the unspecified arguments in turn. The types of these arguments can be determined at run time, by inspecting another argument, for example.

#include <stdarg.h>
void va_start(va_list ap, parameter);
void va_copy(va_list dst, va_list src);
void va_end(va_list ap);
type va_arg(va_list ap, type);

A va_list ap must first be initialized using the va_start macro, specifying the last named parameter. Successive uses of va_arg iterate over the unnamed arguments, indicating the argument type expected at each stage. Finally, va_end must be applied to the iterator to clean up any resources used. It must be used directly in the same block in which the iterator was initialized by va_start.

The type provided to va_arg must match the argument type supplied at the current position. The only exceptions are:

You also have to consider that arguments may be promoted to unexpected types before becoming part of the list; see Arithmetic promotions and Floating-point promotions. Enumeration types are especially unsuitable, as it is not possible to know whether an enumeration type will be promoted to int or long, for example.

Perhaps a future C standard will define a _Promote operator to select the correct type for an enumeration.

va_copy allows a new iterator dst to be initialized as a copy of an existing, and perhaps partially used iterator src. Such a copy can then be passed to another function to be processed separately. There is no way, however, to get the partially iterated list back from the function.

Here's an example use of <stdarg.h>:

#include <stdbool.h>
#include <stdarg.h>
#include <stdio.h>

#define DONE 0
#define INT 1
#define LONG 2
#define DOUBLE 3

void func(int t, ...)
{
  va_list ap;

  va_start(ap, t);

  bool more = true;
  while (more) {
    int i;
    long l;
    double d;

    switch (t) {
    default:
      more = false;
      break;

    case INT:
      i = va_arg(ap, int);
      printf(" %d", i);
      break;

    case LONG:
      l = va_arg(ap, long);
      printf(" %ld", l);
      break;

    case DOUBLE:
      d = va_arg(ap, double);
      printf(" %d", d);
      break;
    }

    t = va_arg(ap, int);
  }

  va_end(ap);
}

func(DONE);
func(DOUBLE, 3.4, INT, 10, LONG, 1009L, DONE);

The classic user of variable-length argument lists is printf and related functions. These also come with v-prefixed alternatives that take a va_list as an argument, e.g., vprintf. If you are thinking of writing a function with a variable-length argument list, it's a good idea to write a v-prefixed version of it first, then build the intended function from it. For example:

void vfunc(int t, va_list ap)
{
  bool more = true;
  while (more) {
    int i;
    long l;
    double d;

    switch (t) {
    default:
      more = false;
      break;

    case INT:
      i = va_arg(ap, int);
      printf(" %d", i);
      break;

    case LONG:
      l = va_arg(ap, long);
      printf(" %ld", l);
      break;

    case DOUBLE:
      d = va_arg(ap, double);
      printf(" %d", d);
      break;
    }

    t = va_arg(ap, int);
  }
}

void func(int t, ...)
{
  va_list ap;
  va_start(ap, t);
  vfunc(t, ap);
  va_end(ap);
}

CHaR
Sitemap Supported
Site format updated 2024-06-05T22:37:07.391+0000
Data updated 1970-01-01T00:00:00.000+0000
Page updated 2022-06-17T21:43:05.000+0000