Stdarg.h


stdarg.h is a header in the C standard library of the C programming language that allows functions to accept an indefinite number of arguments. It provides facilities for stepping through a list of function arguments of unknown number and type. C++ provides this functionality in the header cstdarg.
The contents of stdarg.h are typically used in variadic functions, though they may be used in other functions called by variadic functions.

Declaring variadic functions

are functions which may take a variable number of arguments and are declared with an ellipsis in place of the last parameter. An example of such a function is printf. A typical declaration is

int check;

Variadic functions must have at least one named parameter, so, for instance,

char *wrong;

is not allowed in C. In C, a comma must precede the ellipsis; in C++, it is optional.

Defining variadic functions

The same syntax is used in a definition:

long func;
long func

An ellipsis may not appear in old-style function definitions.

stdarg.h types

NameDescriptionCompatibility
type for iterating argumentsC89

stdarg.h macros

NameDescriptioncompatibility
Start iterating arguments with a va_listC89
Retrieve an argumentC89
Free a va_listC89
Copy contents of one va_list to anotherC99

Accessing the arguments

To access the unnamed arguments, one must declare a variable of type va_list in the variadic function. The macro va_start is then called with two arguments: the first is the variable declared of the type va_list, the second is the name of the last named parameter of the function. After this, each invocation of the va_arg macro yields the next argument. The first argument to va_arg is the va_list and the second is the type of the next argument passed to the function. Finally, the va_end macro must be called on the va_list before the function returns.
C99 provides an additional macro, va_copy, which can duplicate the state of a va_list. The macro invocation va_copy copies va1 into va2.
There is no mechanism defined for determining the number or types of the unnamed arguments passed to the function. The function is simply required to know or determine this somehow, the means of which vary. Common conventions include:
Because the size of the unnamed argument list is generally unknown, there is also no reliable, generic way to forward the unnamed arguments into another variadic function. Even where determining the size of the argument list is possible by indirect means, there is no portable way to pass the dynamically determined number of arguments into the inner variadic call, as the number and size of arguments passed into such calls must generally be known at compile time. To some extent, this restriction can be relaxed by employing variadic macros instead of variadic functions. Additionally, most standard library procedures provide v-prefixed alternative versions which accept a reference to the unnamed argument list instead of the unnamed argument list itself. For example, vfprintf is an alternate version of fprintf expecting a va_list instead of the actual unnamed argument list. A user-defined variadic function can therefore initialize a va_list variable using va_start and pass it to an appropriate standard library function, in effect passing the unnamed argument list by reference instead of doing it by value. Because there is no reliable way to pass unnamed argument lists by value in C, providing variadic API functions without also providing equivalent functions accepting va_list instead is considered a bad programming practice.

Type safety

Some C implementations provide C extensions that allow the compiler to check for the proper use of format strings and sentinels. Barring these extensions, the compiler usually cannot check whether the unnamed arguments passed are of the type the function expects, or convert them to the required type. Therefore, care should be taken to ensure correctness in this regard, since undefined behavior results if the types do not match. For example, if the expected type is int *, then a null pointer should be passed as NULL. Writing just NULL would result in an argument of type either int or void *, neither of which is correct. Another consideration is the default argument promotions applied to the unnamed arguments. A float will automatically be promoted to a double. Likewise, arguments of types narrower than an int will be promoted to int or unsigned int. The function receiving the unnamed arguments must expect the promoted type.
GCC has an extension that checks the passed arguments:

Example


  1. include
  2. include
/* print all args one at a time until a negative argument is seen;
all args are assumed to be of int type */
void printargs
int main

This program yields the output:

5 2 14 84 97 15
84 51

To call other var args functions from within your function you need to use the var arg version of the function :

void MyPrintf

varargs.h

Outdated versions of POSIX defined the legacy header varargs.h, which dates from before the standardization of C and provides functionality similar to stdarg.h. This header is part of neither ISO C nor POSIX. The file, as defined in the second version of the Single UNIX Specification, simply contains all of the functionality of C89 stdarg.h, with the exceptions that: it cannot be used in standard C new-style definitions; you may choose not to have a given argument ; and the way it works is different—in standard C, one would write:

  1. include
int summate

and call with

summate;
summate;
summate;

With varargs.h, the function would be:

  1. include
summate
va_dcl /* no semicolon here! */

and is called the same way.
varargs.h requires old-style function definitions because of the way the implementation works. Conversely, it is not possible to mix old-style function definitions with stdarg.h.