比方说,我有二进制协议,其中前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,因为你说的是"二进制协议"(请参阅前面的问题)