在C数据序列化? [英] Data serialization in C?

查看:201
本文介绍了在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆