【问题标题】:How to get float bit representation without UB in C++?如何在 C++ 中获得没有 UB 的浮点位表示?
【发布时间】:2020-02-10 12:31:33
【问题描述】:

据我所知,所有这样做的“传统”方式,即指针的reinterpret_cast 和带有intfloat 字段的union 都是UB,因为它违反了严格的别名(in C++, not in C) .
那么,如何在没有未定义行为的情况下正确地做到这一点?

我可以对char * 执行reinterpret_cast 并将其存储到uint32_t 吗?或者std::launder 会有所帮助吗?

【问题讨论】:

  • 如果您只想“获取”位表示,您可以简单地将指向float 的指针转换为const unsigned char * 并使用生成的指针来检查对象的字节。但是你为什么提到“memcpy that to float”?复制到float 没有得到位表示;它正在改变位。你真正想做什么?
  • 在 cppcon 2019 上有一个关于这个问题的 1h talk。您可能对此感兴趣。
  • @EricPostpischil 是的,对不起,我的意思是'memcpy to uint32_t`,我会编辑问题。
  • memcpy that to uint32_t - 你为什么要这样做来打印位?您可以从char 打印它们。
  • @KamilCuk 好吧,我想让它们作为一个连续的东西,以获得有效和指数;从 char 数组中获取它们会有点乏味。

标签: c++ strict-aliasing type-punning stdlaunder


【解决方案1】:

正如Jason Turner 所指出的,标准的做法是使用memcpy

float f = 1.0;
std::byte c[sizeof(f)];
memcpy(c, &f, sizeof(f));

您可能认为您不想复制任何内容,只想查看位/字节。好吧,编译器很聪明,他们实际上会优化它,正如 Jason 所证明的那样,所以不要担心,使用 memcpy 处理这种事情,永远不要使用 reinterpret_cast

【讨论】:

  • C++20 std::bit_cast() 值得一提。
  • 没错!这将是执行此操作的标准方式。
  • 我不怕复制,我怕未定义的行为 :) 谢谢!那么std::launder呢?
  • @Amomum std::laundrs 返回类型与其参数类型相同。所以从floatunsigned 的转换是不可能的。
  • @Timo std::launder(reinterpret_cast<uint32_t *>(f)) 怎么样?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多