【问题标题】:How to get the float with given bit-pattern (as int32_t) in C++?如何在 C++ 中获得具有给定位模式(如 int32_t)的浮点数?
【发布时间】:2013-02-13 13:51:43
【问题描述】:

我需要一种快速的方法来获取具有给定位模式的float(提供为int32_t)。当然,编译器应该优化整个构造。简单的转换会进行强制转换并且不允许reinterpret_cast<> ...

【问题讨论】:

  • 为什么不允许 reinterpret_cast?见blogs.msdn.com/b/oldnewthing/archive/2013/02/06/10391383.aspx
  • @JohnZwinck reinterpret_cast<> 在指针类型上是允许的,但这确实需要一个内存位置。不适用于寄存器中的变量
  • *(float*)&int32value。从技术上讲不可移植,但实际上可以在任何地方使用。
  • @PeteBecker:我很确定我过去曾设法说服 GCC 破坏您的代码。但不一定当int32value 是参数时,IIRC 我遇到的破坏是严格的别名违规导致源未初始化。
  • @DavidRodríguez-dribeas 我完全同意你的看法。当前的措辞并没有真正表达我很确定的意图:严格的别名规则以允许更好的优化。但是我承认我不太清楚如何用它来表达我认为需要的东西:可见的演员表和联合访问“工作”就像熟悉系统架构的人所期望的那样,但是如果演员或工会不可见,所有赌注都将取消。问题是在这里精确地指定“可见”的含义。

标签: c++ c++11 type-conversion


【解决方案1】:

编译器会优化它是不可靠的,但它避免了 UB,前提是提供的值确实是浮点数的表示(也就是说,它的大小正确,并且它的位模式不包含陷阱表示float)。 GCC 至少有时能够将其优化掉:

float convert(int32_t inputvalue) {
    float f;
    std::memcpy(&f, &inputvalue, sizeof(f));
    return f;
}

如果优化是问题的重要部分,那么官方的回答是无法保证未知编译器会进行给定的优化。但是这个比大多数更难优化。它依赖于编译器“理解”memcpy 的作用,这比“理解”指针转换的作用更大。

【讨论】:

  • +1 成功使用了这个,VC 2010gcc 4.6 都将它优化为将 32 位内存简单加载到浮动点寄存器。我什至看到这比union-方法得到了更好的优化,至少对于相反的float-to-int 情况(这使得VC使用从内存到浮点寄存器到int寄存器的额外往返)@987654327 @-approach,可能是由于浮动分配)。事实上memcpy 可能看起来很重,但是对于这样简单的操作数,编译器确实知道该怎么做。
【解决方案2】:

唯一完全可移植的方法是通过缓冲区到memcpy

static_assert(sizeof(float) == sizeof(int32_t), "!!");
char buf[sizeof(float)];
memcpy(buf, &i, sizeof(buf));
memcpy(&f, buf, sizeof(buf));

通常可以省略缓冲区:

static_assert(sizeof(float) == sizeof(int32_t), "!!");
memcpy(&f, &i, sizeof(float));

【讨论】:

  • @MarcGlisse direct memcpy(不通过缓冲区)仅在源和目标具有相同类型 (3.9p3) 的情况下定义,但很难看出编译器如何无法直接解释memcpy 符合预期。
  • @ecatmur 是什么让你这么说?无论您是否通过中间缓冲区,所需的语义都是完全相同的。 (两者都是“未定义的行为”,因为源中的位模式可能对应于目标类型中的陷阱值,但您保证获得相同的位模式。)
  • @JamesKanze 3.9p2 将副本复制到缓冲区并返回到原始对象; 3.9p3同类型对象之间直接复制。我可以看到如何将该副本推断为缓冲区并定义了不同类型的对象,但不适用于直接复制。
  • @ecatmur 除了 §3.9/2 明确指出将缓冲区复制回相同类型的对象时定义结果。两段基本相同,第一段为间接复制,第二段为直接复制。标准不能保证更多,因为一种类型的值的某些合法表示将捕获另一种类型的表示。
  • @JamesKanze 我们只对字节序列是两种类型的有效对象表示的情况感兴趣;在这种情况下,标准可以做出保证,但事实并非如此。
猜你喜欢
  • 2020-02-10
  • 1970-01-01
  • 2014-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-23
相关资源
最近更新 更多