是否有使用带有参考参数的可变参数的问题
我有这段代码(总结)...
I have this piece of code (summarized)...
AnsiString working(AnsiString format,...)
{
va_list argptr;
AnsiString buff;
va_start(argptr, format);
buff.vprintf(format.c_str(), argptr);
va_end(argptr);
return buff;
}
并且,在可能的情况下首选通过引用传递的基础上,我因此更改了它.
And, on the basis that pass by reference is preferred where possible, I changed it thusly.
AnsiString broken(const AnsiString &format,...)
{
... the rest, totally identical ...
}
我的调用代码是这样的:-
My calling code is like this:-
AnsiString s1, s2;
s1 = working("Hello %s", "World");
s2 = broken("Hello %s", "World");
但是,s1 包含Hello World",而 s2 包含Hello (null)".我认为这是由于 va_start 的工作方式,但我不确定发生了什么.
But, s1 contains "Hello World", while s2 has "Hello (null)". I think this is due to the way va_start works, but I'm not exactly sure what's going on.
推荐答案
如果你看看 va_start 扩展到什么,你就会明白发生了什么:
If you look at what va_start expands out to, you'll see what's happening:
va_start(argptr, format);
变成(大致)
argptr = (va_list) (&format+1);
如果 format 是一个值类型,它会被放置在所有可变参数之前的堆栈中.如果 format 是引用类型,则只有地址被放置在堆栈中.当您获取引用变量的地址时,您将获得地址或原始变量(在这种情况下是在调用 Broken 之前创建的临时 AnsiString),而不是参数的地址.
If format is a value-type, it gets placed on the stack right before all the variadic arguments. If format is a reference type, only the address gets placed on the stack. When you take the address of the reference variable, you get the address or the original variable (in this case of a temporary AnsiString created before calling Broken), not the address of the argument.
如果你不想传递完整的类,你的选择是通过指针传递,或者放入一个虚拟参数:
If you don't want to pass around full classes, your options are to either pass by pointer, or put in a dummy argument:
AnsiString working_ptr(const AnsiString *format,...)
{
ASSERT(format != NULL);
va_list argptr;
AnsiString buff;
va_start(argptr, format);
buff.vprintf(format->c_str(), argptr);
va_end(argptr);
return buff;
}
...
AnsiString format = "Hello %s";
s1 = working_ptr(&format, "World");
或
AnsiString working_dummy(const AnsiString &format, int dummy, ...)
{
va_list argptr;
AnsiString buff;
va_start(argptr, dummy);
buff.vprintf(format.c_str(), argptr);
va_end(argptr);
return buff;
}
...
s1 = working_dummy("Hello %s", 0, "World");
相关文章