Search code examples
cvariadic-functionsc99

Calling a function with va_list argument needs va_start() at the beggining?


A function with the following header:

int max(int n, va_list vals)

Called inside the function:

int max_first(int n, ...)

Needs a va_start(vals, n) invocation at the body's beginning? I tried without and it works but I don't understand which is the correct way of doing it.

int max(int n, va_list vals)
{
    va_start(vals, n);
    // etc
}

Solution

  • The question is if

    int max(int n, va_list vals)
    

    Called inside the function:

    int max_first(int n, ...)
     
    

    Needs a va_start(vals, n) invocation at the body's beginning?

    No, it does not and it must not, the correct pattern is as follows:

    int max_first(int n, ...) {
        va_list vals;
        va_start(vals, n);
        int rv = max(n, vals);
        va_end(vals);
        return rv;
    }
    

    then

    int max(int n, va_list vals) {
        for (int i = 0; i < n; i ++) {
            int val = va_arg(vals, int);
            ...
        }
    
        ...
    }
    

    i.e. you can call va_start only in a function that has ... and you need to pass in the argument immediately preceding the ..., and each call to va_start must be always followed by va_end for the same value, and if you pass it to a function then you must call va_end right afterwards without using it in the calling function; if you want to process the arguments again, you must then call va_start again.