将va_arg两次传递给相同值的函数结果

时间:2009-12-28 01:35:51

标签: c++ variadic-functions

我正在尝试使用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

导致这种意外行为的原因是什么?

3 个答案:

答案 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的内部状态以注册已处理的参数,并且在参数评估期间执行此操作两次时,未指定发生的情况。您的编译器及其使用的优化似乎导致传递两个相同的参数。

相关问题