c - 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 上运行了结果:
- 版本 1909(操作系统版本 18363.1440)-> 调试和发布:
1717.789063
- 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 版本中的错误
解决方案
我发现了 Windows 版本和调试/发布模式之间程序行为不同的原因。
新的 Windows 更新(19041.* 如果我理解正确)更改了浮点类型小数部分的舍入规则:以前它在以 5: 结尾的情况下舍入到更大1.25 -> 1.3
,但现在它舍入到最接近的偶数: 1.25 -> 1.2
, 1.35 -> 1.4
。
要了解在新 Win 10 版本上调试和发布之间的区别,需要注意ucrtbase.dll的使用和更新规则。
- 每个应用程序的调试和发布版本都使用C:\Windows\System32 或 C:\Windows\SysWOW64中的ucrtbase.dll或ucrtbased.dll
- 它的发行版 ( 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 版本上都相同。
推荐阅读
- netsuite - 无法使用 ss2.0 动态创建 Restlet
- c++ - 使用 yaml-cpp 更新 YAML 文档的节点和值
- visual-studio-code - 如何为 Chrome(或 Edge)扩展设置调试器以正确断点在 wwwroot 之外提供的源文件?
- python - 代码未按预期打印碰撞时刻
- c# - 在 C# 中单击时,您可以将按钮变成图像吗?
- sql - select 子句中位置 16 'D_INS_COMPANY.ORDER_BY' 的错误行 1 既不是聚合也不是 group by 子句
- linux - awk、拆分和打印一系列列
- karate - 如何结合重试创建动态路径组件,直到
- c# - 点击 Geckofx 网络浏览器内的链接将触发 Winforms 中的方法
- android - Android WebView:手机锁定时音频断断续续