Passing on va_arg twice to a function result in same value
I'm trying to use va_arg to make a generic factory function in my GUI library. When passi开发者_开发百科ng va_arg twice in the same function they pass on the same value instead of two different:
GUIObject* factory(enumGUIType type, GUIObject* parent, ...){
va_list vl;
va_start(vl, parent);
...
label->SetPosition(va_arg(vl, int), va_arg(vl, int));
va_end(vl);
return finalObjectPointer;
}
factory(LABEL, theParent, 100,200); // Results in position 200:200
What causes this unexpected behavior?
The compiler is not guaranteed to evaluate arguments in order. Add some additional local variables and do the two assignments in sequence.
See this other stack overflow posting.
int v1 = va_arg(vl, int);
int v2 = va_arg(vl, int);
label->SetPosition(v1, v2);
To get what you are observing: the exact same value twice -- probably requires a compiler bug piled on top of the undefined order of evaluation situation, or some entertaining aspect of the particular macro expansion of va_arg in your environment.
va_arg
is a macro. What's hiding behind that macro is implementation defined, which means that it is quite possible that operations performed in place of va_arg
have side effects. For this reason, it is not a good idea to use va_arg
more than once between two adjacent sequence points. This is potentially undefined behavior, meaning that anything can happen. Looks like this is exactly what happens in your case, which results in this "weird" behavior when you get two identical values from va_arg
.
Even if there's no undefined behavior in some implementation, the order of argument evaluation in a function call is unspecified, meaning that using any "sequential readers" in the way you use them is not guaranteed to work as intended (whatever it is you intended).
There are no sequence points in between the evaluations of different arguments, so modifying the same value (vl
or something it refers to) twice while evaluating the arguments leads to unspecified behaviour.
va_arg
changes the internal state of vl
to register which arguments are already handled, and when doing this twice during argument evaluation it is unspecified what happens. Your compiler and the optimizations it uses seem to result in two identical parameters being passed.
精彩评论