Variable Length Arguments in C

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.
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.


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

/* this function will take the number of values to average
   followed by all of the numbers to average */
double average ( int num, ... )
    va_list arguments;                     
    double sum = 0;
    int x;

    /* Initializing arguments to store all values after num */
    va_start ( arguments, num );           
    /* Sum all the inputs; we still rely on the function caller to tell us how
     * many there are */
    for (x = 0; x < num; x++ )        
        sum += va_arg ( arguments, double ); 
    va_end ( arguments );                  // Cleans up the list

    return sum / num;                      

int main()
    /* this computes the average of 13.2, 22.3 and 4.5 
    (3 indicates the number of values to average) */
    printf( "%f\n", average ( 3, 12.2, 22.3, 4.5 ) );
    /* here it computes the average of the 5 values 3.3, 2.2, 1.1, 5.5 and 3.3
    printf( "%f\n", average ( 5, 3.3, 2.2, 1.1, 5.5, 3.3 ) );*/