varargs(va_list va_start) doesn't work with pass-by-reference parameter [duplicate]

北城以北 提交于 2019-12-03 23:57:19

问题


Possible Duplicate:
Are there gotchas using varargs with reference parameters

Hi, I have a problem with varargs. Look at my code(Microsoft Visual Studio 2005 or 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;
}

function T1, T2 work well. But T3 function have a problem. The pointer p doesn't point "Test3". Can't I use va_start with pass-by-reference? Thanks in advance.


回答1:


You cannot use references with va_start according to C++ Standard 18.7/3:

The restrictions that ISO C places on the second parameter to the va_start() macro in header are different in this International Standard. The parameter parmN is the identifier of the rightmost parameter in the variable parameter list of the function definition (the one just before the ...). If the parameter parmN is declared with a function, array, or reference type, or with a type that is not compatible with the type that results when passing an argument for which there is no parameter, the behavior is undefined.




回答2:


Short answer: no, you cannot do that.

NOTE: I saw the first answer which quotes the standard but I believe it is worth showing also my tests.

va_start is defined like this:

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

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

With this code:

#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;
}

output

char ref:1
int ref:4

Since at implementation level references are passed on stack in a similar way to pointers this represents a problem since the size differs (it is because of the macro which computes the size of the type not taking into account that the parameter is actually a reference, which is not constant but depends on actual size of the type).



来源:https://stackoverflow.com/questions/3184401/varargsva-list-va-start-doesnt-work-with-pass-by-reference-parameter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!