在C数据序列化? [英] Data serialization in C?
问题描述
我有这样的结构,我想写一个文件:
I have this structure which I want to write to a file:
typedef struct
{
char* egg;
unsigned long sausage;
long bacon;
double spam;
} order;
这个文件必须是二进制,并且必须由具有任何机器可读
C99编译器。
This file must be binary and must be readable by any machine that has a C99 compiler.
我看着各种方法这个问题,如ASN.1,XDR,XML,
ProtocolBuffers和许多其他人,但没有一个适合我的要求:
I looked at various approaches to this matter such as ASN.1, XDR, XML, ProtocolBuffers and many others, but none of them fit my requirements:
- 小
- 简单
- 写在 C
- small
- simple
- written in C
然后我决定让我自己的数据的协议。我可以处理
下面的整数类型的再presentations:
I decided then to make my own data protocol. I could handle the following representations of integer types:
- 无符号
- 签署的的补的
- 签署的补的
- 在签署的符号和幅度的
在
在
- unsigned
- signed in one's complement
- signed in two's complement
- signed in sign and magnitude
在一个有效,简单和干净的方式(IM pressive,不是吗?)。然而,
真正类型现在是一个痛苦。
in a valid, simple and clean way (impressive, no?). However, the real types are being a pain now.
我应该如何读浮动
和双击
从字节流?标准
说,按位运算符(至少&安培;
, |
,<<
和>>
)是
整数只类型,其中给我留下没有希望。唯一的办法我可以
认为是:
How should I read float
and double
from a byte stream? The standard
says that bitwise operators (at least &
, |
, <<
and >>
) are for
integer types only, which left me without hope. The only way I could
think was:
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);
但似乎并没有真正有效的。我也找不到重新presentation说明双
和浮动
。应该怎样
这前一继续?
but that doesn't seem really efficient. I also could not find a
description of the representation of double
and float
. How should
one proceed before this?
推荐答案
如果你想尽可能便携用浮漂,您可以使用frexp和ldexp:
If you want to be as portable as possible with floats you can use frexp and 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的precision通常至少高达尾数(没有保证的宽度,但它是一个有效假设,我不知道一个单一的架构,不同的是这里)。
The Idea behind this is, that ldexp, frexp and INT_MAX are standard C. Also the precision of an unsigned long is usually at least as high as the width of the mantissa (no guarantee, but it is a valid assumption and I don't know a single architecture that is different here).
因此,转换工作没有precision损失。用INT_MAX司/乘法可能会失去一个位转换期间precision的,但是这是一个妥协的人可以住在一起。
Therefore the conversion works without precision loss. The division/multiplication with INT_MAX may loose a bit of precision during conversion, but that's a compromise one can live with.
这篇关于在C数据序列化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!