Variable length arguments (var-args) in C

In the journey of learning C functions, we learned many concepts related to functions. We learned to define our own function, passing arguments to a function, returning value from a function, recursive function etc. In this chapter, I will talk something interesting about passing variable length arguments to a function.

Have you ever wondered how functions like printf() and scanf() works? As they readily accept any number of arguments passed. You can say –

printf("Learning at Codeforwin");                // Single argument
printf("Codeforwin was founded in %d", 2015);    // Two arguments
printf("Today is %d-%d-%d", 19, 9, 2017);        // Four arguments

In real you can pass n number of arguments to printf(), but how it works?

What is variable length arguments (var-args)?

In programming, there happens situation when you want your function to accept variable number of arguments. For example – suppose I ask you to write a function to find maximum. You will end up with function declaration similar to

int maximum(int n1, int n2, int n3); // Find maximum between three numbers
OR
int maximum(int n1, int n2, int n3, int n4, int n5); // Find maximum between five numbers

However, none of the above declaration is suitable for the case. First function will find maximum between three numbers likewise second will find maximum of five numbers. What if I need to find maximum between four, ten or sometime n numbers. For such case, we use variable length arguments in a function.

Variable length arguments is a programming construct that allows programmers to pass n number of arguments to a function. You can also call variable length argument as var-args.

Syntax of using variable length arguments

return_type function_name(parameter_list, int num, ...);
  • Return type – Specify function return type.
  • Function name – Name of the function.
  • Parameter list – This is optional for var-args function. If your function accepts parameter other than var-args, then pass it before var-args.
  • int numint num specify number of variable length arguments passed.
  • Ellipsis symbol … – Specify that the function is ready to accept n number of arguments.

Macros used in variable length arguments

You cannot access variable length arguments directly. Header file stdarg.h provide macros that support access to var-args. To implement var-args in our program we will use following macros definitions.

  • va_list – Data type to define a va_list type variable.
  • va_start – Used to initialize va_list type variable.
  • va_arg – Retrieves next value from the va_list type variable.
  • va_end – Release memory assigned to a va_list variable.

Note: Do not confuse yourself with the word macro. For now think it as a function, I will cover it separately in later sections.

How to use variable length arguments in a function?

Follow six simple steps to implement variable length arguments in your function.

  1. Include stdarg.h header file to access variable length argument.
  2. Define a function to accept variable length arguments.
    void myfunction(int num, ...);
  3. Inside function create a va_list type variable.
    va_list list;
  4. Initialize list variable using va_start macro. va_start macro accepts two parameters. First va_list type variable and number of arguments in the list.
    va_start(list, num);
  5. Run a loop from 1 to number of arguments. Inside the loop, use va_arg to get next argument passed as variable length arguments. va_arg accepts two parameter. First va_list type variable from where to fetch values. Second, type (data type) of value you want to retrieve.
    va_arg(list, int);
  6. Finally release memory occupied by va_list using va_end.
    va_end(list);

Example program to use variable length arguments

Write a C function to accept n number of arguments using variable length arguments. Return maximum of all values.

/**
 * C program to find maximum among n arguments
 */

#include <stdio.h>
#include <stdarg.h> // Used for var-args
#include <limits.h> // Used for INT_MIN

/* Variable length arguments function declaration */
int maximum(int num, ...);

int main()
{
    /*
     * Test var-args with some sample values.
     */
    printf("Max(10,2) = %d\n", maximum(2, 10, 2));
    printf("Max(4,2,3,0) = %d\n", maximum(4, 4, 2, 3, 0));

    printf("Max(1,2,3,4,10,20,30) = %d\n", maximum(7, 1, 2, 3, 4, 10, 20, 30));
    printf("Max(100,10,0,1,2,3,4,10,20,12) = %d\n", maximum(10, 100, 10, 0, 1, 2, 3, 4, 10, 20, 12));
    return 0;
}


/**
 * Variable length arguments function definition.
 * num  Total number of arguments passed.
 * ...  Variable length arguments
 * Returns maximum value among n integer
 */
int maximum(int num, ...)
{
    int max = INT_MIN;
    int count; // Loop counter variable
    int value; // Store the value of current argument in var-args

    // Declare va_list type variable
    va_list list;

    // Initialize the list
    va_start(list, num);

    /*
     * Run loop from 1 to number of arguments passed
     */
    for(count=1; count<=num; count++)
    {
        // Get next argument in list
        value = va_arg(list, int);

        /*
         * If current argument is greater than max
         * then store it in max.
         */
        if(value > max)
            max = value;
    }

    // Clean the list
    va_end(list);

    // Finally return max argument in list
    return max;
}

Output –

Max(10,2) = 10
Max(4,2,3,0) = 4
Max(1,2,3,4,10,20,30) = 30
Max(100,10,0,1,2,3,4,10,20,12) = 100

Limitations of variable length arguments

Variable length arguments exhibits a great advantage of passing n number of arguments to a function. However, there are few limitations of using var-args.

  • Arguments passed as var-args must be of same type.
  • You must pass variable length arguments as last parameter. For example –
    int max(int num, ... , int some_variable);   // Error
    int max(... , int some_variable);            // Error
    int max(... , int num, float some_variable); // Error 
    int max(int some_variable, int num, ...);    // OK

Despite of its own advantages and disadvantages, I recommend you make less use variable length arguments. You can easily replace any variable length arguments function by passing array to a function.