简体   繁体   English

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

[英]Precision loss when passing arguments using va_list and printf

I have a logging function which works like this: 我有一个日志功能,其工作方式如下:

// 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");
}

(Side note: This should do the exact same thing as just a normal printf, so it's pretty useless in this state. That's because this is a minumal working example. In the end, this should work with ncurses - see commented section.) (旁注:这应该与普通的printf完全相同,因此在这种状态下它是无用的。这是因为这是一个极小的工作示例。最后,这应该与ncurses一起使用 - 请参阅注释部分。)

I then create an instance of the ConsoleUI class, called ui: 然后我创建一个名为ui的ConsoleUI类的实例:

ConsoleUI ui;

And later I use it to log stuff, more precisely, a time_duration in microseconds: 后来我用它来记录东西,更确切地说,是一个以微秒为单位的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());

The output I get: 我得到的输出:

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

What I expected: 我的期望:

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

Note that over multiple calls of this, the values in the last two lines change slightly (as is to be expected of a delta time) and the first two values don't change - which looks like there's something wrong with the format. 请注意,通过多次调用,最后两行中的值稍有变化(如预期的增量时间),前两个值不会改变 - 这看起来格式有问题。

So, bottom line: Calling printf directly works, but passing it down the logger and then calling printf doesn't work... 所以,底线:调用printf直接工作,但将其传递给记录器,然后调用printf不起作用...

Since you can't actually pass your arguments from log to printf , you are passing a va_list - this is the right solution, but you can't pass a va_list to printf. 由于您实际上无法将参数从log传递给printf ,因此您传递的是va_list - 这是正确的解决方案,但您无法将va_list传递给printf。

This line: 这一行:

    printf( format.c_str(), args);

prints args with the format in format . 打印args与格式format Given that args is of the type va_list (typically implemented in the comiler ABI as a void pointer) it will not represent the data that you expect in the format string. 假设args的类型为va_list (通常在编译器ABI中作为void指针实现),它将不代表您在格式字符串中所期望的数据。 If you use 如果你使用

   vprintf( format.c_str(), args);

it should work just fine, that's what vprintf is for. 它应该工作得很好,这就是vprintf的用途。

(Note that it's nothing to do with "loss of precision" - it's passing incorrect type of argument to printf - and since it's a programmaticly formulated string, even enabling warnings is not going to work). (请注意,它与“精度损失”无关 - 它将不正确的参数类型传递给printf - 并且因为它是一个程序化的字符串,即使启用警告也不会起作用)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM