我正在尝试使用va_arg在我的GUI库中创建一个通用工厂函数。 当在同一个函数中传递va_arg两次时,它们传递相同的值而不是两个不同的值:
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
导致这种意外行为的原因是什么?
答案 0 :(得分:6)
不保证编译器按顺序评估参数。添加一些其他局部变量并按顺序执行两个分配。
请参阅this其他堆栈溢出发布。
int v1 = va_arg(vl, int);
int v2 = va_arg(vl, int);
label->SetPosition(v1, v2);
获取您正在观察的内容:完全相同的值两次 - 可能需要在评估情境的未定义顺序之上堆积编译器错误,或者在您的环境中va_arg的特定宏扩展的某些有趣方面。
答案 1 :(得分:6)
va_arg
是一个宏。隐藏在该宏背后的是实现定义,这意味着代替va_arg
执行的操作很可能具有副作用。因此,在两个相邻序列点之间不止一次使用va_arg
不是一个好主意。这可能是未定义的行为,这意味着任何事情都可能发生。看起来这正是您的情况下发生的情况,当您从va_arg
获得两个相同的值时会导致这种“奇怪”的行为。
即使某些实现中没有未定义的行为,函数调用中参数求值的顺序是未指定,这意味着在使用它们的方式中使用任何“顺序读取器”并不能保证按预期工作(无论你想要什么)。
答案 2 :(得分:2)
在不同参数的评估之间没有序列点,因此在评估参数时修改相同的值(vl
或其引用的东西)两次会导致未指定的行为。
va_arg
更改vl
的内部状态以注册已处理的参数,并且在参数评估期间执行此操作两次时,未指定发生的情况。您的编译器及其使用的优化似乎导致传递两个相同的参数。