简体   繁体   中英

How to properly va_end?

#include <cstdarg>
using namespace std;

void do_something( va_list numbers, int count ) {
//                         ^
// Should I call this by reference here? I mean, va_list & numbers?
    //... stuff
    va_end( numbers );
}

void setList( int count, ... ) {
    va_list numbers;
    va_start( numbers, count );
    do_something( numbers, count );
}

int main() {
    setList( 2, 0, 1 );
    return 0;
}

When taking va_list to another function, how should I pass it to that function? I know that va_end must be called when things are done with va_list I'm confused whether I should call it by reference or not. Will va_list be properly ended even though it is not called by reference?

Variable argument lists:

You should never use va_end in a function taking the va_list as argument!

From the (Linux) man-page for va_arg :

Each invocation of va_start() must be matched by a corresponding invocation of va_end() in the same function .

(Emphasis mine)

In a function having a va_list argument, take the va_list by value (as C-library functions like vprintf , ... do, too).

Example:

#include <cstdarg>
#include <iostream>

void v_display_integers(int count, va_list ap) {
    while(0 < count--) {
        int i = va_arg(ap, int);
        std::cout << i << '\n';
    }
}

void display_integers(int count, ...) {
    va_list ap;
    va_start(ap, count);
    v_display_integers(count, ap);
    va_end(ap);

    // You might use 'va_start' and 'va_end' a second time, here.
    // See also 'va_copy'.
}

int main() {
    display_integers(3, 0, 1, 2);
}

Note:

In C++ you should avoid variable argument lists. Alternatives are std::array , std::vector , std::initializer_list and variadic templates.

I prefer to call va_end in the same function in which I called va_start or va_copy, like any other resource allocation/deallocation pair. That style is required by the standard, although some implementations are more tolerant.

Normally, va_lists are passed by value. They are small objects.

The macro function va_end is implemented as either void statement or resetting the va_list variable.

http://research.microsoft.com/en-us/um/redmond/projects/invisible/include/stdarg.h.htm

Theoretically, you can call it anywhere, or even skip it. However, to be a good programmer, we need to put it after the va_ functions

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM