Reputation: 345
#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?
Upvotes: 5
Views: 1274
Reputation:
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.
Upvotes: 8
Reputation: 513
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
Upvotes: 1
Reputation: 241691
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.
Upvotes: 1