2010-07-06 118 views
12

可能重複:
Are there gotchas using varargs with reference parameters可變參數(參數va_list的va_start)不與通按引用參數工作

嗨,我有可變參數的問題。 看看我的代碼(Microsoft Visual Studio 2005或2008)。

#include <stdarg.h> 

struct Test { int a; }; 

void T1(int n, ...) { 
va_list args; 
va_start(args, n); 
char* p = va_arg(args, char*); 
va_end(args); 
} 

void T2(Test n, ...) { 
va_list args; 
va_start(args, n); 
char* p = va_arg(args, char*); 
va_end(args); 
} 

void T3(const Test& n, ...) { 
va_list args; 
va_start(args, n); 
char* p = va_arg(args, char*); // p corrupt!! 
va_end(args); 
} 

int _tmain(int argc, _TCHAR* argv[]) { 
const Test t; 
T1(1, "Test1"); 
T2(t, "Test2"); 
T3(t, "Test3"); 
return 0; 
} 

函數T1,T2工作正常。但T3功能有問題。指針p不指向「Test3」。我不能使用帶引用傳遞的va_start嗎? 在此先感謝。

+2

它表現出g ++中的預期行爲,但這並不意味着太多,是嗎? – 2010-07-06 07:57:13

回答

13

不能根據C++標準18.7/3 va_start使用引用:

該第二參數在頭 所述的va_start()宏ISO C的地方是在本國際標準不同的限制。參數parmN是函數定義的變量參數列表中最右邊的參數(緊挨......之前的那個參數)的標識符。 如果使用函數,數組或參考類型聲明參數parmN,或者將不兼容的類型 與傳遞沒有參數的參數傳遞的類型相結合,則行爲爲 未定義。

4

簡答:不,你不能這樣做。

注:我看到了引用標準的第一個答案,但我相信這值得展示我的測試。

va_start的定義如下:

視覺6:#define va_start(ap,v) (ap = (va_list)&v + _INTSIZEOF(v))

視覺8:#define _crt_va_start(ap,v) (__va_start(&ap, _ADDRESSOF(v), _SLOTSIZEOF(v), \ __alignof(v), _ADDRESSOF(v)))

有了這個代碼:

#include <cstdio> 

int main() 
{ 
    char c; 
    char &rc = c; 
    int i; 
    int &ri = i; 

    printf("char ref:%d\n", sizeof(rc)); 
    printf("int ref:%d\n", sizeof(ri)); 

    return 0; 
} 

輸出

char ref:1 
int ref:4 

由於在實現級別引用以類似於指針的方式傳遞到堆棧上,這表示一個問題,因爲大小不同(這是因爲計算類型大小的宏沒有考慮參數實際上是參考,它不是恆定的,而是取決於類型的實際大小)。

+1

謝謝。這真有趣。 :) – 2010-07-06 23:57:22