c - C中的数据序列化?

标签 c serialization floating-point

我有一个要写入文件的结构:

typedef struct
{
    char* egg;
    unsigned long sausage;
    long bacon;
    double spam;
} order;

这个文件必须是二进制的,并且必须可以被任何具有 C99编译器。

我研究了解决这个问题的各种方法,例如 ASN.1、XDR、XML、 ProtocolBuffers 和许多其他的,但没有一个符合我的要求:

  • 简单
  • C 编写

然后我决定制定自己的数据协议(protocol)。我可以应付 整数 类型的以下表示:

  • 未签名
  • 签署了自己的补充
  • checkin 补码
  • 签署符号和大小

以有效、简单和干净的方式(令人印象深刻,不是吗?)。但是,那 真正的类型现在很痛苦。

我应该如何阅读 floatdouble来自字节流?标准 表示按位运算符(至少 &|<<>> )用于 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/

相关文章:

c - free() 函数不起作用

java - 如何读取写在文件中的 LinkedHashMap?

javascript - 存储信息(如果 Number 是浮点型或整数)

c - Malloc 不会创建具有所需大小的结构数组

c - 套接字地址已在使用中 - 一开始忘记了 SO_REUSEADDR

c - C程序内存错误,名称消失?

java - 序列化 JTable 的 TableModel

Javascript:反序列化对象和混合方法

floating-point - 在什么范围内,整数算术加法和减法可以精确到 IEEE double 浮点中的整数?

c - 级联 hypot() 安全吗?