为什么 Boost 格式和 printf 在同一格式字符串上的行为不同

Why do Boost Format and printf behave differently on same format string

本文关键字:格式 字符串 printf 为什么 Boost      更新时间:2023-10-16

Boost Format 文档说:

它的目标之一是提供printf的替代品,这意味着 格式可以解析为 printf 设计的格式字符串,将其应用于 给定参数,并产生与 printf 相同的结果。

当我使用相同的格式字符串比较 boost:format 和 printf 的输出时,我得到了不同的输出。在线示例在这里

#include <iostream>
#include <boost/format.hpp>
int main()
{
    boost::format f("BoostFormat:%d:%X:%c:%d");
    unsigned char cr =65; //'A'
    int cr2i = int(cr);
    f % cr % cr % cr % cr2i;
    std::cout << f << std::endl;
    printf("Printf:%d:%X:%c:%d",cr,cr,cr,cr2i);
}

输出为:

增强格式: A:A:A:65

打印: 65:41:A:65

区别在于当我想将字符显示为整数类型时。

为什么会有区别?这是错误还是想要的行为?

这是

预期行为。

在提升手册中,它写了你使用的经典类型规范:

但是 printf 的经典类型规范标志较弱 格式的含义。它只是在 内部流和/或格式化参数,但不需要 要具有特定类型的相应参数。

另请注意,在 stdlib-printf 调用中,所有char参数都是自动的。由于 vararg-call 而转换为 int。因此,生成的代码与以下内容相同:

printf("Printf:%d:%X:%c:%d",cr2i,cr2i,cr2i,cr2i);

此自动转换不是使用 % 运算符完成的。

对接受答案的补充:

这也发生在类型 wchar_t 以及 unsigned short 和其他等效类型的参数上,这可能是意外的,例如,在 Windows API 中使用结构的成员(例如,SYSTEMTIME (时,由于历史原因,它们是 WORD 类型的短整数。

如果您使用Boost Format来替代遗留代码中的printf和"类似printf"的函数,则可以考虑创建一个包装器,该包装器以转换的方式覆盖%运算符

  • charshort int
  • unsigned charunsigned short unsigned int

以模拟 C 变量参数列表的行为。它仍然不是100%兼容的,但大多数剩余的不兼容实际上有助于修复潜在的不安全代码。

较新的代码可能不应该使用Boost格式,而是使用标准std::format,这与printf不兼容。