使用va_list和printf传递参数时精度损失

时间:2014-05-12 07:47:02

标签: c++ printf variadic-functions

我有一个日志功能,其功能如下:

// public function:
void ConsoleUI::log(const std::string& format, ...) {
    va_list args;
    va_start(args, format);
    log(format, args);
    va_end(args);
}

// overloaded private function:
void ConsoleUI::log(const std::string& format, va_list args) {
    //wprintw( outWin, format.c_str(), args);
    //wprintw( outWin, "\n");
    printf( format.c_str(), args);
    printf( "\n");
}

(旁注:这应该与普通的printf完全相同,所以在这种情况下它是无用的。那是因为这是一个极小的工作示例。最后,这个应该使用ncurses - 请参阅注释部分。)

然后我创建了一个名为ui:

的ConsoleUI类的实例
ConsoleUI ui;

后来我用它来记录东西,更确切地说,是一个以微秒为单位的time_duration:

now = boost::posix_time::microsec_clock::local_time();
boost::posix_time::time_duration delta = now - lastTime;
double dt = 1e-6*(double)delta.total_microseconds();
lastTime = now;

ui.log( "logged dt: %f", dt );
ui.log( "logged dt 2: %lu", delta.total_microseconds());
printf( "dt: %f\n", dt);
printf( "dt 2: %lu\n", delta.total_microseconds());

我得到的输出:

logged dt: 0.000000
logged dt 2: 140736013247624
dt: 0.018739
dt 2: 18739

我的期望:

logged dt: 0.018739
logged dt 2: 18739
dt: 0.018739
dt 2: 18739

请注意,通过多次调用,最后两行中的值会略有变化(正如预期的增量时间),并且前两个值不会发生变化 - 这看起来就像那里一样。格式有问题。

所以,底线:调用printf直接工作,但是将它传递给记录器,然后调用printf不起作用......

1 个答案:

答案 0 :(得分:2)

由于您无法将参数从log传递到printf,因此您传递了va_list - 这是正确的解决方案,但您无法做到将va_list传递给printf。

这一行:

    printf( format.c_str(), args);

args格式打印format。假设args属于va_list类型(通常在编译器ABI中作为void指针实现),它将不代表您在格式字符串中所期望的数据。如果你使用

   vprintf( format.c_str(), args);

它应该工作得很好,这是vprintf的用途。

(请注意,它与&#34无关;精度损失" - 它将不正确的参数类型传递给printf - 并且因为它是一个程序化的字符串,即使启用警告也不会起作用。)