在按值传递va_list参数从一个成员函数到另一个成员函数时,我遇到了访问冲突错误(使用Microsoft Visual C ++ 2005)。如果我通过引用传递它,一切按预期工作但va_list不应该通过引用传递,是吗?
class A
{
public:
char * getformatted( char const * a_format, ... )
{
va_list argp;
va_start( argp, a_format );
char * result = getformatted( a_format, argp );
va_end( argp );
return result;
}
char * getformatted( char const * a_format, va_list /*&*/ a_args )
{
static char buffer[ 256 ];
int length = vsprintf( buffer, a_format, a_args ); // Access violation.
return buffer;
}
};
int main( int argc, char * argv[] )
{
char * str = A().getformatted( "foo%s", "bar" );
return 0;
}
答案 0 :(得分:2)
在<stdarg.h>
:
typedef char * va_list
所以A().getformatted( "foo%s", "bar" )
正在调用A::getformatted( char const * a_format, va_list /*&*/ a_args)
,原因是由于C兼容性导致字符串文字衰减到char *
。
答案 1 :(得分:1)
如果您单步执行,是否按预期顺序调用了两个函数?
所显示的两个功能都有相似的签名,因此首先要检查是否确保呼叫正常进行。这一点尤为重要,因为va_list
通常是char *
的typedef,所以getformatted("foo%s", "bar")
可以在不首先调用getformatted(const char *, ...)
的情况下调用。{/ p>
如果是这种情况,并且vsprintf
在任何时候都使用va_next
,则行为将是未定义的。有些编译器将va_
函数作为简单宏处理,而其他编译器则具有重要功能。
通常要解决此问题,va_list
的函数将以v
(vsprintf
等)作为前缀,以消除任何潜在的歧义。
在最好的情况下,由于您使用的是C ++,因此通常首选std::stringstream
或boost::format
。两者都会为您提供类型安全性并防止大多数类似情况,而后者保留了大部分printf
的语法。