如何在 C++ 中获得没有 UB 的浮点位表示?
Posted
技术标签:
【中文标题】如何在 C++ 中获得没有 UB 的浮点位表示?【英文标题】:How to get float bit representation without UB in C++? 【发布时间】:2020-02-10 12:31:33 【问题描述】:据我所知,所有这样做的“传统”方式,即指针的reinterpret_cast
和带有int
和float
字段的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 数组中获取它们会有点乏味。
【参考方案1】:
正如Jason Turner 所指出的,标准的做法是使用memcpy
:
float f = 1.0;
std::byte c[sizeof(f)];
memcpy(c, &f, sizeof(f));
您可能认为您不想复制任何内容,只想查看位/字节。好吧,编译器很聪明,他们实际上会优化它,正如 Jason 所证明的那样,所以不要担心,使用 memcpy
处理这种事情,永远不要使用 reinterpret_cast
。
【讨论】:
C++20std::bit_cast()
值得一提。
没错!这将是执行此操作的标准方式。
我不怕复制,我怕未定义的行为 :) 谢谢!那么std::launder
呢?
@Amomum std::laundr
s 返回类型与其参数类型相同。所以从float
到unsigned
的转换是不可能的。
@Timo std::launder(reinterpret_cast<uint32_t *>(f))
怎么样?以上是关于如何在 C++ 中获得没有 UB 的浮点位表示?的主要内容,如果未能解决你的问题,请参考以下文章