浮点数的字节序问题

4
我正在使用std::fstream在C++中编写和读取二进制数据(std::ios::binary),其中包括整数和浮点值。虽然我的代码在本地架构上可以正常工作,但我希望确保它是可移植的,即在具有不同字节顺序的计算机上仍能正确读取由本机生成的二进制文件。因此,我的想法是在二进制文件的第一个字节中添加一个值,该值将指示文件的字节顺序。
由于整数和浮点数的字节顺序可能不同,我需要分别获取这两种数据类型的信息。对于整数,通过指针算术运算获得字节顺序相对简单,但我不知道如何在运行时获取浮点数的字节顺序。有什么想法吗?
我的代码如下:
#include <cstdint>

#define INT_LITTLE_ENDIAN     0x01u
#define INT_BIG_ENDIAN        0x02u
#define FLOAT_LITTLE_ENDIAN   0x04u
#define FLOAT_BIG_ENDIAN      0x08u

uint8_t getEndianess(){
  uint8_t endianess = 0x00;
  uint16_t integerNumber = 0x1;
  uint8_t *numPtr = (uint8_t*)&integerNumber;
  if (numPtr[0] == 1) {
    endianess |= INT_LITTLE_ENDIAN;
  }else {
    endianess |= INT_BIG_ENDIAN;
  }
  /* TODO: check endianess for float */
  return endianess;
}

获取整数的字节序非常简单。但是,发布的代码无法很好地处理较不常见的字节序,例如PDP字节序 - chux - Reinstate Monica
3个回答

3

除了字节序,还有可能会出现非 IEEE-754 格式,但这是相当罕见的。

如果你可以假设是 IEEE-754 二进制格式,那么它几乎肯定使用与整数相同的字节序,但你可以通过使用一个负幂次的浮点值(比如 -1.0),来检查其是否具有非零的 MSbyte(包含符号和部分指数)和零的 LSbyte(包含最低有效位数)。

float floatNumber = -1.0;
uint8_t *numPtr = (uint8_t*)&floatNumber;
if (numPtr[0] == 0) {
  endianess |= FLOAT_LITTLE_ENDIAN;
} else {
  endianess |= FLOAT_BIG_ENDIAN;
}

3

假设浮点数的符号位在最高位(例如IEEE标准),并且它们不是像二进制补码那样的表示方式,你可以轻松地创建一个数字,对其取反,并检查第一个或最后一个字节是否发生了变化。


2

检查 float 字节序的同时也是对编码的检查。

如果编码不是 float32,则检测它。

不要使用多个零字节的字节模式(如0xBF800000 (-1.0f)),而应考虑使用每个字节期望的字节模式不同的模式。同时检查每个字节。

  const float f = -0x1.ca8642p-113f;  // 0x87654321, IEEE-754 binary32
  if (sizeof(float) != 4) {
    printf("float is not 4 bytes\n");
  } else if (memcmp(&f, (uint8_t[4]){0x87, 0x65, 0x43, 0x21}, sizeof f) == 0) {
    printf("Big\n");
  } else  if (memcmp(&f, (uint8_t[4]){0x21, 0x43, 0x65, 0x87}, sizeof f) == 0) {
    printf("Little\n");
  } else {
    printf("Unknown\n");  // TBD endian or float encoding
  }

示例:非IEEE-754二进制32位,其中符号位在第二个字节中。 - chux - Reinstate Monica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接