2010-07-06 119 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