检查符号位的位置是否足以确定 IEEE-754 浮点数相对于整数字节序的字节序?

sax*_*one 7 c++ floating-point portability endianness ieee-754

我最近编写了一些代码,用于memcpyfloat/解包double为适当宽度的无符号整数,然后使用一些位移将符号位与组合的有效数字/指数分开。

\n
\n

注意:对于我的用例,我不需要将后两部分彼此分开,但我确实需要它们以正确的顺序排列,即:{sign, (exponent, significand)},后一个元组包装为足够宽度的无符号整数。

\n
\n

我的代码运行良好,经过彻底测试,没有任何问题;然而,我有点震惊地发现 IEEE-754 没有指定其二进制交换格式 \xe2\x80\x94 的字节顺序,据我所知,这意味着我的位移位在极少数情况下float endianness \xe2\x89\xa0 integer endianness

\n

根据此处回答的问题,我的假设是,鉴于位移位与存储中的实际字节序无关,我只需要担心浮点数的字节序是否与整数的字节序匹配。
\n我松散地遵循链接答案中的代码设计了以下代码,但避免通过指针强制转换使用类型双关,这对我来说似乎是未指定/未定义的行为领域:

\n
#include <cstdint>\n#include <cstring>\n\n// SAME means "same as integer endianness"\nenum class FloatEndian { UNKNOWN, SAME, OPPOSITE, };\n\nFloatEndian endianness() {\n    float check = -0.0f; // in IEEE-754, this should be all-zero significand and exponent with sign=1\n    std::uint32_t view;\n    std::memcpy(&view, &check, sizeof(check));\n    switch (view) {\n    case 0x80000000: // sign bit is in most significant byte\n        return FloatEndian::SAME;\n    case 0x00000080: // sign bit is in least significant byte\n        return FloatEndian::OPPOSITE;\n    default: // can\'t detect endianness of float\n        return FloatEndian::UNKNOWN;\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

如果我确保我的浮标确实是 IEEE-754 std::numeric_limits<T>::is_iec559,那么我的方法是否是一种可靠且可移植的方法,可以确保在切碎浮标时“以正确的方式”获得浮标?

\n

chu*_*ica 3

检查符号位的位置是否足以确定 IEEE-754 浮点数相对于整数字节序的字节序?

  • 当我读到它时,考虑到 C++ 规范和它往往也依赖的 C 规范,检查符号位在技术上不足以确定float/uint32_t. 这实际上可能已经足够了,因为除大/小之外的字节序很少见,而且float/uint32_t字节序之间也存在差异。

  • 我建议使用一个与 不同的常量-0.0f,也许-0x1.ca8642p-113f它具有模式 0x87654321 并且将是更彻底的字节序测试。非常不清楚为什么OP想要使用一个位稀疏-0.0f来辨别3个可能的结果。

  • 正如其他人所提到的,在 C++ 中,测试应该是编译时测试,因此与仅测试符号位的简单性相比,彻底性并不是运行时成本。

  • 依赖is_iec559于 true 可能会不必要地限制可移植性,因为要做到这一点,需要许多非有限的合规性规则。 参考号 您的代码真的需要安静且有信号的 NAN 吗?

  • 另请参阅如果is_iec559为 true,这是否意味着我可以以明确定义的方式提取指数和尾数?

  • 我希望 OP 也能测试sizeof(float) == sizeof(uint32_t)elsememcpy(&view, &check, sizeof(check))是坏代码。

我的方法是否是一种强大且便携的方法,可以确保在切碎浮标时“以正确的方式”获得浮标?

  • 代码并不像它应有的那样健壮和可移植。

  • “当我把它们切碎时”-->该代码没有显示,所以无法回答。我怀疑用于endianness()支持“使用 memcpy 将 float/double 解包为适当宽度的无符号整数,然后使用一些位移位将符号位与组合有效数字/指数分开”的目标。正是该代码值得审查。