帮助理解C stdarg宏(va_start ...)

时间:2010-07-19 10:22:36

标签: c variadic-functions

最近我遇到了这个函数(用在logger类中)。我理解它做什么,但我不知道如何

void Reporter::print( const char* szFormat, ...)
{
    // note: m_out is a FILE*
    va_list args;
    va_start(args, szFormat);
    vfprintf( m_out, szFormat, args);
    va_end(args);
}

我读了reference,但我还不清楚。最让我烦恼的是,这不能按预期工作。我为最后一个数字得到0,为字符串得到(null),尽管它应该打印一个大于0的数字和一个文件的路径。

案例1:

rep.print( "Values: %08X %08X %08X %08X %08X %08X %d %s\n", val1, val2, val3, val4, val5, val6, source.GetLength(), szPath );
// source.GetLength() returns a size_t, szPath is a const char* and IS indeed a valid string

但是改成它可以正常工作:

案例2:

rep.print( "Values: %08X %08X %08X %08X %08X %08X", val1, val2, val3, val4, val5, val6 );
rep.print( " %d %s\n", source.GetLength(), szPath );

请注意,我正在MSVC ++ 2008下编译。相同的代码在gcc下工作正常(即使是第一种情况)。 Reporter :: print()的实现或我使用函数的方式是否有错误?即使在第一种情况下调用它,我怎样才能确保它能正常工作?为什么它甚至会失败?

1 个答案:

答案 0 :(得分:3)

Reporter::print的代码很好。它所做的只是正确初始化args以引用变量参数列表,然后将该变量参数列表传递给vfprintf(),它知道如何处理它。

您的问题很可能是%d格式说明符(需要int类型参数)与source.GetLength()返回的值的类型不匹配(我会猜测可能是size_t)。如果你知道长度总是适合int,那么你可以通过强制转换解决它:

..., (int)source.GetLength(), ...

(这是因为编译器不知道作为变量参数列表一部分的预期类型的​​参数,不像普通的原型函数声明)。