C - Function Variable Number Arguments

Introduction

Some functions can accept a variable number of arguments.

The functions printf() and scanf_s() are examples.

The standard library stdarg.h provides you with routines to write some of your own.

A function with a variable number of parameters has the following prototype:

double average(double v1, double v2, ...);

The ellipsis indicates that a variable number of arguments may follow the first two fixed arguments.

You must have at least one fixed argument.

You need to use va_start(), va_arg(), and va_end() to process the Arguments.

The first function has the following form:

void va_start(va_list parg, last_fixed_arg);

The name, va_start, means variable argument start.

This function accepts two arguments:

  • a pointer parg of type va_list, and
  • the name of the last fixed parameter.

The va_list type is a type that is defined in stdarg.h and stores information for variable argument lists.

We can start to write the function as follows:

double average(double v1, double v2,...)
{
  va_list parg;              // Pointer for variable argument list
  // More code to go here...
  va_start( parg, v2);
  // More code to go here...
}

va_start() sets the variable parg to point to the first variable argument that is passed to the function.

We must determine the type of each variable argument.

The average() function deals with arguments of type double.

The following code shows how to access the value of each of the variable arguments:

double average( double v1, double v2,...){
  va_list parg;              // Pointer for variable argument list
  double sum = v1 + v2;      // Accumulate sum of the arguments
  double value = 0.0;        // Argument value
  int count = 2;             // Count of number of arguments

  va_start(parg,v2);         // Initialize argument pointer
  while((value = va_arg(parg, double)) != 0.0)
  {
    sum += value;
    ++count;
  }
  va_end(parg);              // End variable argument process
  return sum/count;
}

Look at the loop condition:

while((value = va_arg(parg, double)) != 0.0)

The loop condition calls va_arg().

The first argument to va_arg() is the variable parg initialized by va_start().

The second argument is a specification of the type of the argument.

The function va_arg() returns the value of the current argument specified by parg via value.

When an argument value obtained is 0.0, the loop ends:

va_end(parg);                // End variable argument process

va_end() cleans up the process.

It resets the parg pointer to NULL.

Demo

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

double average(double v1, double v2, ...);       // Function prototype

int main(void)
{
  double v1 = 10.5, v2 = 2.5;
  int num1 = 6, num2 = 5;
  long num3 = 12L, num4 = 20L;

  printf("Average = %.2lf\n", average(v1, 3.5, v2, 4.5, 0.0));
  printf("Average = %.2lf\n", average(1.0, 2.0, 0.0));
  printf("Average = %.2lf\n", average((double)num2, v2, (double)num1,
    (double)num4, (double)num3, 0.0));
  return 0;/*ww w.j ava 2s .  co m*/
}

// Function to calculate the average of two or more arguments
double average(double v1, double v2, ...)
{
  va_list parg;                                  // Pointer for variable argument list
  double sum = v1 + v2;                          // Accumulate sum of the arguments
  double value = 0.0;                            // Argument value
  int count = 2;                                 // Count of number of arguments

  va_start(parg, v2);                             // Initialize argument pointer
  while ((value = va_arg(parg, double)) != 0.0)
  {
    sum += value;
    ++count;
  }
  va_end(parg);                                  // End variable argument process
  return sum / count;
}

Result

Copying a va_list

stdarg.h header va_start() makes a copy of parg like this:

va_list parg_copy;
va_copy(parg_copy, parg);