【问题标题】:C++ Type Wrapper printf prints wrong value for floatC++ 类型包装器 printf 打印错误的浮点值
【发布时间】:2015-05-11 17:30:52
【问题描述】:

我尝试为基本类型编写一个包装类,但在使用 printf 时遇到了问题。

由于某种原因,printf 可以与 int 一起使用,但不能与 float 一起使用。 std::cout 但是两者都可以正常工作。

当我明确地转换为浮动时,printf 当然可以正常工作。

template <typename T>
class Type
{
public:
    Type() : _mData() {}
    Type(const T& _data) : _mData(_data) {}

    operator T() const { return _mData; }
    operator std::string() const { return std::to_string(_mData); }

private:
    T _mData;
};

int main(void)
{
    Type<int> someInt(200);

    std::cout << "int" << std::endl;
    std::cout << "std::cout: " << someInt <<std::endl; 
    printf("printf: %d\n\n", someInt);


    Type<float> someFloat(300.3);
    std::cout << "float" << std::endl;
    std::cout << "std::cout: " << someFloat <<std::endl; 
    printf("printf: %f\n\n", someFloat);

    return 0;
}

output:
int
std::cout: 200
printf: 200

float
std::cout: 300.3
printf: 0.000000

为什么它适用于 int?

为什么它不适用于浮动?

如何在不显式转换的情况下使其正常工作?

【问题讨论】:

  • 它对 int 起作用(或看起来)的原因与它对 float 不起作用的原因相同。在这两种情况下,它都是未定义的行为。 printf 不是类型安全的,并且不可扩展以处理不在其规范中的类型。
  • 特别是,您的转换永远不会被调用,因为没有理由调用它们,您没有将类型传递给期望 float 的函数。所以Type 被传入,它恰好在正确的位置有int 的表示。在 ideone 上,float 也位于正确的位置。在您的编译器中,似乎正在发生其他事情。但谁在乎呢,不管怎样,它都坏了,看起来工作更糟。
  • 好像是这样。是否有可能获得我的班级的内部字节表示?

标签: c++ types printf wrapper typecasting-operator


【解决方案1】:

为什么它适用于 int?

它是UB。在您的特定机器上,它恰好可以工作。

为什么它不适用于浮动?

原因同上。

如何在不显式转换的情况下使其正常工作?

直接来说,你不能。 printf 是为 C 创建的,当时 C++ 还不存在(并且 OOP 不是 printf 设计中的考虑因素)。因此,printf 不能扩展为新类型。

您可以创建一个包装函数,对 printf 支持的类型进行转换(显式)并在内部调用 printf。这很麻烦,容易出错等等。

这是 c++ iostream 相对于 [s|f]printf 系列函数的主要优势之一。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-10
    相关资源
    最近更新 更多