独立于平台的有符号整数存储



我想以与平台无关的方式将有符号整数值写入文件。

如果它们是无符号的,我只需将它们从主机字节顺序转换为带有端序(3)函数族的LE(或BE)。

我不知道如何处理有符号整数。如果我将它们转换为无符号值,就会丢失符号,因为C标准不保证

(int) ((unsigned) -1)) == -1

另一种选择是我转换一个指向值的指针(即,将字节序列重新解释为无符号),但我不相信在此之后转换端序会给出任何有意义的东西。

平台无关的有符号整数存储的正确方法是什么?

:

  • 我知道在实践中,几乎所有的体系结构都使用双补表示,因此我可以在有符号整数和无符号整数之间进行无损转换。然而,这是一个更理论化的问题。

  • 只是推出我自己的整数表示(将十进制字母存储为ascii字符,或单独存储符号位)当然是一个解决方案。但是,我很感兴趣的是,是否有一种方法可以在不完全放弃本机二进制表示的情况下工作。

最简单的解决方案:

对于书写,只需转换为无符号并使用您的无符号端序转换函数。

对于回读值,首先将它们读入无符号变量,检查高位是否设置,并进行一些算术运算以使转换定义良好:

uint32_t temp;
int32_t dest;
if (temp > INT32_MAX) dest = -(int32_t)(-temp-1)-1;
else dest = temp;

作为一个额外的奖励,一个好的编译器在一个相同的系统上(即一个双补系统,其中实现定义的转换为unsigned是"正确的")将首先优化-(int32_t)(-temp-1)-1(int32_t)temp,然后优化条件的两个分支,现在它们都包含相同的代码,到一个没有分支的代码路径

独立于平台的方式?如果您真的想要这样,您应该考虑将其写成文本而不是二进制(并且考虑到即使也不是完全与平台无关的,因为您可能希望将其从ASCII移动到EBCDIC平台)。

这完全取决于如何与平台无关。C允许三种不同的符号编码:二进制补码,二进制补码和符号/大小。但是,到目前为止,大多数机器将使用第一种方法。

首先要弄清楚这个词的真正含义。如果你的意思是你只想处理2的补数,那么将其转换为unsigned是可以的。

使用与通过网络发送数据时相同的方法。将您的无符号或有符号值转换为大端,并使用htonl()保存它们。读取时,使用ntohl()将数据转换回您的机器端序。

但是像往常一样,您需要知道数据最初是有符号的还是无符号的。只有一个位序列,你不能确定。

选项:

  • 使用类似printf()的函数将数字存储为纯文本
  • 将负数转换为符号+绝对值,将其存储为无符号的,带有额外的符号位

输出一个1字节的符号标志(例如0=正,1=负)。如果值为负,则将其改为正,然后以大端格式写入该值。如果你不喜欢0和1,你可以使用'+'和'-'。

将符号和绝对值存储为2个字段,并在读取时重新组合。

你说你已经知道如何从一个定义良好的字节顺序转换到/,所以剩下的就是确定符号(提示<0可能在这里有帮助:-)),取绝对值(您可以结合确定它是什么,或使用abs()或类似的方法)。

类似:

if (num < 0) {
  negative = 1;
   num      = -num;
 } else {
   negative = 0
 }
write_value = htole32(num);
write(file, &negative, 1);
write(file, &write_value, 4);

作为一种优化,您可以将值的符号位收集在一起,并将它们存储在绝对值之前的单个单词中。

最新更新