首页 > 解决方案 > Win10破解printf函数

问题描述

#include <stdio.h>
int main()
{
    float f = 1717.7890625;
    printf( "%.6f", f );
    return 0;
}

我使用 Visual Studio 19 (16.9.2) for x64 arch 编译了这段代码,并在我的两台 Windows 10 PC 上运行了结果:

  1. 版本 1909(操作系统版本 18363.1440)-> 调试和发布:1717.789063
  2. 2004 版(操作系统内部版本 19041.867)-> 调试:1717.789063发布:1717.789062

新版本的 Debug 和 Release 结果不同的原因是什么?如何修复它以使两个版本的结果相同?

补充: 代码:

#include <stdio.h>
int main()
{
    double f = 0.25;
    printf( "%.1f", f );
    return 0;
}

在新旧 Win10 版本上具有相同的行为。我建议,这是较新的 ucrtbase.dll 版本中的错误

标签: cwindows-10printf

解决方案


我发现了 Windows 版本和调试/发布模式之间程序行为不同的原因。

新的 Windows 更新(19041.* 如果我理解正确)更改了浮点类型小数部分的舍入规则:以前它在以 5: 结尾的情况下舍入到更大1.25 -> 1.3,但现在它舍入到最接近的偶数: 1.25 -> 1.2, 1.35 -> 1.4

要了解在新 Win 10 版本上调试和发布之间的区别,需要注意ucrtbase.dll的使用和更新规则。

  1. 每个应用程序的调试和发布版本都使用C:\Windows\System32 或 C:\Windows\SysWOW64中的ucrtbase.dllucrtbased.dll
  2. 它的发行版 ( ucrtbase.dll )是 Windows 10 的一部分,只能通过 Windows 更新进行更新。但它的调试版本(ucrtbased.dll)不会随 Win 10 更新而更新,但可以通过安装较新的 Windows 10 SDK(例如,在 Visual Studio 安装程序中)进行更新。

因此,解决方案是在新的 Windows 10 版本上安装新的 Windows 10 SDK 以实现相同的行为或将 printf() 函数从https://github.com/fmtlib/fmt切换到 fmt::printf() 函数,例如, 使结果在所有 Windows 版本上都相同。


推荐阅读