2009-12-28 27 views
1

我試圖使用va_arg在我的GUI庫中創建一個通用工廠函數。 當路過的va_arg兩次他們傳遞相同的值,而不是兩個不同的相同的功能:將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

使用va_arg函數更多的是一個實驗,我可能不會在我的GUI庫中使用它,但是知道是什麼原因會很有趣。 – Zoomulator 2009-12-28 01:37:49

回答

6

編譯器不保證按順序評估參數。添加一些額外的局部變量並按順序執行兩個分配。

請參閱this其他堆棧溢出發佈。

int v1 = va_arg(vl, int); 
int v2 = va_arg(vl, int); 

label->SetPosition(v1, v2); 

爲了得到你所觀察到的:完全相同的值的兩倍 - 可能需要堆在評估情況,或在va_arg的特定宏擴展的一些娛樂方面的不確定順序的頂部編譯器故障而您環境。

2

在評估參數時,在不同參數的評估之間沒有序列點,因此在評估參數時兩次修改相同的值(vl或其引用的內容)會導致未指定的行爲。

va_argvl的內部狀態更改爲註冊哪些參數已處理,並且在參數評估期間執行兩次操作時,未指定會發生什麼情況。您的編譯器及其使用的優化似乎會導致傳遞兩個相同的參數。

6

va_arg是一個宏。隱藏在該宏後面的是實現定義的,這意味着很有可能在va_arg處執行的操作具有副作用。由於這個原因,在兩個相鄰序列點之間多次使用va_arg並不是一個好主意。這可能是未定義的行爲,意味着任何事情都可能發生。看起來這正是你的情況,當你從va_arg得到兩個相同的值時會導致這種「奇怪」的行爲。

即使有一些方面沒有未定義的行爲,論證評價的函數調用的順序是不確定,這意味着在使用它們的方式使用任何「連續讀者」是不能保證工作打算(不管你打算如何)。