我想以独立于平台的方式将有符号整数值写入文件。
如果它们是无符号的,我只需将它们从主机字节顺序转换为具有endian(3)函数族的LE(或BE)。
我不知道如何处理有符号整数。如果我将它们转换为无符号值,我会松开符号,因为C标准不保证
(int) ((unsigned) -1)) == -1
另一种选择是我转换指向值的指针(即,将字节序列重新解释为无符号),但是我不相信在此之后转换字节序会给出任何合理的结果。
平台无关的有符号整数存储的正确方法是什么?
更新:
我知道在实践中,几乎所有架构都使用双补码表示,这样我就可以在有符号和无符号整数之间进行无损转换。然而,这个问题意味着更具理论性。
只是推出我自己的整数表示(将十进制字母存储为ascii字符,或单独存储符号位)当然是一种解决方案。但是,如果有一种方法可以在不完全放弃原生二进制表示的情况下工作,我很感兴趣。
答案 0 :(得分:3)
最简单的解决方案:
编写时,只需转换为无符号并使用无符号字节序转换函数。
为了读取值,首先将它们读入无符号变量,并检查是否设置了高位,并进行一些算术以使转换定义良好:
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
,然后将条件的两个分支(现在都包含相同的代码)优化到没有分支的单个代码路径。
答案 1 :(得分:1)
独立于平台的方式?如果真正想要这个,你应该考虑把它写成文本而不是二进制(并考虑到即使 不完全独立于平台,因为你可能想要移动它从ASCII到EBCDIC平台。)
这一切都取决于 如何平台无关。 C允许三种不同的有符号编码:两个补码,一个补码和符号/幅度。但是,到目前为止,大多数机器都会使用第一台机器。
首先确定该术语的实际含义。如果你的意思是你只想处理两个补码,那么将它转换为无符号就好了。
答案 2 :(得分:1)
使用与通过网络发送数据时相同的方法。将未签名或签名的值转换为big-endian,并使用htonl()
保存它们。阅读时,使用ntohl()
将数据转换回计算机字节序。
但与往常一样,您需要知道数据最初是签名还是未签名。只需要一点序列,你就无法确定。
答案 3 :(得分:0)
选项:
答案 4 :(得分:0)
输出1字节符号标志(例如0 =正,1 =负)。如果值为负,则将其设置为正,然后以big endian格式写入值。如果你不喜欢0和1,你可以使用'+'和' - '。
答案 5 :(得分:0)
将符号和绝对值存储为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);
作为优化,您可以一起收集值的符号位,并将它们存储在绝对值之前的单个字中。