sax*_*one 7 c++ floating-point portability endianness ieee-754
我最近编写了一些代码,用于memcpy
将float
/解包double
为适当宽度的无符号整数,然后使用一些位移将符号位与组合的有效数字/指数分开。
\n\n注意:对于我的用例,我不需要将后两部分彼此分开,但我确实需要它们以正确的顺序排列,即:
\n{sign, (exponent, significand)}
,后一个元组包装为足够宽度的无符号整数。
我的代码运行良好,经过彻底测试,没有任何问题;然而,我有点震惊地发现 IEEE-754 没有指定其二进制交换格式 \xe2\x80\x94 的字节顺序,据我所知,这意味着我的位移位在极少数情况下float endianness \xe2\x89\xa0 integer endianness。
\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
,那么我的方法是否是一种可靠且可移植的方法,可以确保在切碎浮标时“以正确的方式”获得浮标?
检查符号位的位置是否足以确定 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 吗?
我希望 OP 也能测试sizeof(float) == sizeof(uint32_t)
elsememcpy(&view, &check, sizeof(check))
是坏代码。
我的方法是否是一种强大且便携的方法,可以确保在切碎浮标时“以正确的方式”获得浮标?
代码并不像它应有的那样健壮和可移植。
“当我把它们切碎时”-->该代码没有显示,所以无法回答。我怀疑用于endianness()
支持“使用 memcpy 将 float/double 解包为适当宽度的无符号整数,然后使用一些位移位将符号位与组合有效数字/指数分开”的目标。正是该代码值得审查。