我有一个日志记录功能,如下所示:

// 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一起使用-参见注释部分。)

然后,我创建一个ConsoleUI类的实例,称为ui:

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是行不通的...

最佳答案

由于您实际上无法将参数从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的目的。

(请注意,这与“精度损失”无关-它向printf传递了错误的参数类型-并且由于它是以编程方式编写的字符串,因此即使启用警告也无法正常工作)。

关于c++ - 使用va_list和printf传递参数时的精度损失,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23603601/

10-17 01:32