Variadic functions

C/C++ language supports variable argument function or variadic function. The prototype defines a single defined argument along with "..." (three dots) to indicate it as Variadic function. Printf and scanf library functions are the best examples of variadic functions.

int printf (const char * str_format, ...); 

Variadic functions can take a variable number of arguments and they are optional by nature. Variadic functions should have at least one argument and after that "..." should be added to indicate that this function takes variable arguments. Header file contains type va_list and other variable argument utility macros to write these functions.

Variadic types & macros

Variadic arguments are managed with the help of list and macros and these are defined in header file These

  • va_list (type) - Main type used in Variadic function, holds the information needed by macros va_start, va_arg, va_end, and va_copy.
  • va_start (macro) - takes the fixed argument as input and starts of iterations in the variadic function arguments
  • va_arg (macro) - obtain the current variadic function argument, and advances to the next location in stack
  • va_copy (macro) - makes a copy of the variadic function arguments (Available only in C99)
  • va_end (macro) - ends of iteration in the variadic function arguments, used at the end of the iteration.
#define va_start(ap,v)  ( ap = (va_list)&v + _INTSIZEOF(v) )
#define va_arg(ap,t)    ( *(*)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define va_end(ap)      ( ap = (va_list))

Variadic function example

This is one simple example of Variadic function demonstrating how printf/scanf function works.

#include <stdio.h>
#include <stdarg.h>
 
void v_printf(int count, ...)
{
    va_list args;
    int i;
    va_start(args, count);
    printf ("variadic : argument count = %d\n", count);
    for (= 0; i < count; i++) {
     printf("argument %d = %d, ", i + 1, va_arg(args, int));
    }
    printf ("\n");
    va_end(args);
}
 
int main(void)
{
    v_printf(0); 
    v_printf(1,10);
    v_printf(2,10,20);
    v_printf(3,10,20,30);  
}

Variadic functions output

./a.out
variadic : argument count = 0

variadic : argument count = 1
argument 1 = 10, 
variadic : argument count = 2
argument 1 = 10, argument 2 = 20, 
variadic : argument count = 3
argument 1 = 10, argument 2 = 20, argument 3 = 30,

Variadic function example 2

This is another simple example of Variadic function for calculating average of numbers.

#include <stdio.h>
#include <stdarg.h>
 
float average(int count, ...)
{
    va_list args;
    int i;
    float avg = 0;
    va_start(args, count);
    for (= 0; i < count; i++) {
     avg += (float)va_arg(args, int);
    }

    va_end(args);
    return avg/(float)count;
}
 
int main(void)
{
    float avg;
    avg = average(2, 1, 2);
    printf("average of 1, 2 = %f\n", avg); 
    avg = average(3, 1, 2, 3);
    printf("average of 1, 2, 3 = %f\n", avg); 
    avg = average(4, 1, 2, 3, 4);
    printf("average of 1, 2, 3, 4 = %f\n", avg);
    return 0;
}

Variadic functions output

./a.out 
average of 1, 2 = 1.500000
average of 1, 2, 3 = 2.000000
average of 1, 2, 3, 4 = 2.500000

Variadic function and arguments

Arguments are pushed in the stack from right to left one by one. Each argument takes a size of integer in stack. For data types whose sizes are greater than integer, double or multiples of integer size are taken.

fixed variadic arguments in program stack

#include <stdarg.h>
 
void v_printf(int count, ...)
{
    va_list args;
    int i;
    va_start(args, count);
    for (= 0; i < count; i++) {
     va_arg(args, int); 
    }
    va_end(args);
}

Inside the function, we take the va_list and initialize with the first argument. va_start() macro takes the address of the first argument and advances itself to the next argument. Now with each iteration we call va_arg() which actually returns the value of the current type and the pointer to the next argument. In this way we get the value of each argument and the va_list pointer advances to the next argument.

About our authors: Team EQA

You have viewed 1 page out of 252. Your C learning is 0.00% complete. Login to check your learning progress.

#