为什么 Boost Format 和 printf 在相同的格式字符串上表现不同

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

The Boost Format documentation 说:

One of its goal is to provide a replacement for printf, that means format can parse a format-string designed for printf, apply it to the given arguments, and produce the same result as printf would have.

当我使用相同的格式字符串比较 boost:format 和 printf 的输出时,我得到了不同的输出。网上例子是here

#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

printf: 65:41:A:65

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

为什么会有差异?这是错误还是需要的行为?

这是预期的行为。

boost manual 中写了关于您使用的经典类型规范:

But the classical type-specification flag of printf has a weaker meaning in format. It merely sets the appropriate flags on the internal stream, and/or formatting parameters, but does not require the corresponding argument to be of a specific type.

另请注意,在 stdlib-printf 调用中,所有 char 参数都会自动 由于可变参数调用,转换为 int。所以生成的代码等同于:

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

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

除了

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

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

  • charshortint
  • unsigned charunsigned shortunsigned int

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

较新的代码可能不应该使用 Boost 格式,而是 standard std::format,它与 printf.

不兼容