如何在c++中以二进制格式打包数据

How to pack data in binary format in c++

本文关键字:包数据 数据 格式 二进制 c++      更新时间:2023-10-16

比方说,我有二进制协议,其中前4位表示一个小于或等于10(十进制十)的数值。

在C++中,我可以使用的最小数据类型是char,它有8位长。因此,在我的应用程序中,我可以在一个char变量中保存由4位表示的值。我的问题是,如果我必须将char值打包回4位进行网络传输,我该如何将char值包装回4位?

您对char执行逐位操作;

所以

  unsigned char packedvalue = 0;
  packedvalue |= 0xF0 & (7 <<4);
  packedvalue |= 0x0F & (10);

将4个最高位设置为7,将4个低位设置为10

作为再次打开包装

 int upper, lower;
 upper = (packedvalue & 0xF0) >>4;
 lower = packedvalue & 0x0F;

作为这个问题的一个额外答案,您可能还想查看协议缓冲区,以获得对二进制传输数据进行编码和解码的方法。

当然,只需使用一个字符来表示您的值:

std::ofstream outfile("thefile.bin", std::ios::binary);
unsigned int n;  // at most 10!
char c = n << 4; // fits
outfile.write(&c, 1);  // we wrote the value "10"

较低的4位将保留为零。如果它们也用于某些东西,那么在编写c之前,您必须完全填充它

infile.read(&c, 1);
unsigned int n = c >> 4;

嗯,有流行但不可移植的"位字段"。它们符合标准,但可能会在不同的平台上创建不同的包装订单。所以不要使用它们。

然后,还有高度可移植的位移位和逐位and和OR运算符,这是您应该更喜欢的。从本质上讲,您需要处理更大的字段(对于TCP/IP协议,通常为32位),并提取或替换位的子序列。请参阅Martin的链接和Soren的回答。

您熟悉C的位字段吗?你只需写

struct my_bits {
  unsigned v1 : 4;
  ...
};

请注意,对位字段的各种操作速度较慢,因为编译器必须对它们进行解包以进行加法之类的操作。我可以想象,尽管需要多条指令,但打开一个位字段的速度仍然会比添加操作本身快,但这仍然是开销。逐位操作应该保持相当快。平等也是如此。

您还必须注意endianness和线程(有关详细信息,请参阅我链接的维基百科文章,但问题有点明显)。不管怎样,你应该了解endianness,因为你说的是"二进制协议"(请参阅前面的问题)