Saturday, December 31, 2011

Example of using variadic functions in C

This is the translation into English of an old post.

In my master's thesis I used variadic functions (functions that can accept a variable number of arguments) to be able to pass different differential equations systems to the function in charge of computing Lyapunov exponents.

Since that code is too big to fit in here, I'll post the tiny tests that I did to understand how C variadic functions work.

You can find a great explanation of C variadic functions in a section of apendix A of The GNU C Library manual. In this manual there is an example in which an undetermined number of integers is passed to a function that adds them.

This is the example where I've highlighted and commented the most important lines:

int sum (int count,...){
    va_list ap; // List of arguments
    int i, sum;

    /* Initializes the list of arguments */
    va_start (ap, count);         

    sum = 0;
    for (i = 0; i < count; i++){
        /* Obtains the next argument */
        sum += va_arg (ap, int);    
    /* Frees the list */
    va_end (ap);       
    return sum;

int main(void){
    /* This prints 16. */
    printf ("%d\n", sum (3, 5, 5, 6));

    /* This prints 19. */
    printf ("%d\n", sum (10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
    return (0);

Several important things regarding this example must be remarked:
  • To work with an undetermined number of arguments we must include the header stdarg.h of the C Standard Library.
  • In the function's list of arguments three dots are used to signal the start of the undetermined arguments.
  • A variable of type va_list must be declared. This variable will contain the arguments list.
  • The macro va_start is used to initialize the arguments list. We must tell the macro which is the last determined argument.
  • The macro va_arg is used tp extract the arguments from the list. We must tell the macro the type of the extracted argument. 
  • The macro va_end is used to free the memory.  
This is the result of executing the previous example:
$ ./test1 

In the next example, I used the same procedure to pass an undetermined number of arguments. In this case, though, the type of the argument is a user defined type:
#include <stdarg.h> 
#include <stdio.h>

typedef struct s_Date{
    unsigned int year;
    unsigned int month;
    unsigned int day;

void setDate(unsigned int day, unsigned int month, unsigned int year, 
             t_Date *date);
void printDate(t_Date date);

/* Prints several dates */
void printDates(unsigned int numberOfDates, ...){
    va_list ap;
    int i;

    /* Initializes the list of arguments */
    va_start(ap, numberOfDates);         

    for(i = 0; i < numberOfDates; i++){
        // Extracts next argument from the list
        printDate(va_arg (ap, t_Date));
    // Frees the memory

int main(void){
    t_Date date1, date2, date3;
    setDate(1,1,2009, &date1);
    setDate(2,2,2009, &date2);
    setDate(3,3,2009, &date3);
    /* This prints 1/1/2009 */
    printDates(1, date1);

    /* This prints  1/1/2009 2/2/2009*/
    printDates(2, date1, date2);
    /* This prints 1/1/2009 2/2/2009 3/3/2009*/
    printDates(3, date1, date2, date3);

    return (0);

/* Initializes a t_Date variable*/
void setDate(unsigned int day, unsigned int month, unsigned int year, 
             t_Date *date){
    date->day = day;
    date->month = month;
    date->year = year;

/*Prints a date*/
void printDate(t_Date date){
    printf("%d/%d/%d ",, date.month, date.year);
This is the output:
$ ./test2 
1/1/2009 2/2/2009 
1/1/2009 2/2/2009 3/3/2009 

No comments:

Post a Comment