我有一个要写入文件的结构:
typedef struct
{
char* egg;
unsigned long sausage;
long bacon;
double spam;
} order;
这个文件必须是二进制的,并且必须可以被任何具有 C99编译器。
我研究了解决这个问题的各种方法,例如 ASN.1、XDR、XML、 ProtocolBuffers 和许多其他的,但没有一个符合我的要求:
- 小
- 简单
- 用 C 编写
然后我决定制定自己的数据协议(protocol)。我可以应付 整数 类型的以下表示:
- 未签名
- 签署了自己的补充
- checkin 补码
- 签署符号和大小
以有效、简单和干净的方式(令人印象深刻,不是吗?)。但是,那 真正的类型现在很痛苦。
我应该如何阅读 float
和 double
来自字节流?标准
表示按位运算符(至少 &
、 |
、 <<
和 >>
)用于
integer 类型,这让我没有希望。我唯一能做的
认为是:
int sign;
int exponent;
unsigned long mantissa;
order my_order;
sign = read_sign();
exponent = read_exponent();
mantissa = read_mantissa();
my_order.spam = sign * mantissa * pow(10, exponent);
但这似乎并不是很有效。我也找不到
double
的表示说明和 float
.应该怎样
在此之前进行?
最佳答案
如果你想使用 float 尽可能便携,你可以使用 frexp 和 ldexp:
void WriteFloat (float number)
{
int exponent;
unsigned long mantissa;
mantissa = (unsigned int) (INT_MAX * frexp(number, &exponent);
WriteInt (exponent);
WriteUnsigned (mantissa);
}
float ReadFloat ()
{
int exponent = ReadInt();
unsigned long mantissa = ReadUnsigned();
float value = (float)mantissa / INT_MAX;
return ldexp (value, exponent);
}
这背后的想法是,ldexp、frexp 和 INT_MAX 是标准 C。此外,unsigned long 的精度通常至少与尾数的宽度一样高(不能保证,但这是一个有效的假设,我不知道这里有什么不同的架构)。
因此转换工作没有精度损失。 INT_MAX 的除法/乘法在转换过程中可能会失去一点精度,但这是一个可以接受的折衷方案。
关于c - C中的数据序列化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5608370/