2012-01-16 35 views
3

说,我有二进制协议,其中前4位表示可以小于或等于10(十进制十)的数值。如何在C++中以二进制格式打包数据

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

+3

请参阅http://stackoverflow.com/questions/443265/where-can-i-find-a-bit-shifting-guide-for -c – 2012-01-16 22:48:05

回答

3

当然,只使用一个字符为你的价值:

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。阅读:

​​
+0

n << 4将n移位4这意味着它将使用“更重要”位。数字是8或9的问题是它将使用最重要的位。因此,我的建议是使用“无符号字符”,尤其是回读。 – CashCow 2012-01-16 23:22:25

+0

以上是写8位..我的问题是,我怎么写只有4位到输出流在C + + – Jimm 2012-01-16 23:51:51

+0

@Jimm:自然,你不能,因为最小的可寻址单位是一个'字符'。然而,您可以*先读取*一个字节,只处理其高四位,并将结果写回。 – 2012-01-17 01:10:05

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; 

作为一个额外的问题的答案 - - 您也可以查看protocol buffers以获取二进制传输数据的编码和解码方法。

+0

恢复值时,需要注意签名。 – 2012-01-16 22:55:28

+0

@Ben,只要你打包正数,无符号字符应该照顾 - 但是如果你计划打包一个负数 - (比如-2)到一个位字段,那么你可能需要做一些更多的代码。 – Soren 2012-01-16 22:59:22

+0

为什么我需要做0xF0&(7 << 4),当它产生与7 << 4相同的结果? – Jimm 2012-01-16 23:22:38

3

那么,有流行的,但不便携的“位场”。它们符合标准,但可以在不同平台上创建不同的打包顺序。所以不要使用它们。

然后,有高度便携的位移和按位AND和OR操作符,您应该更喜欢。本质上,你在一个更大的领域工作(通常是TCP/IP协议的32位)并提取或替换位的子序列。请参阅Martin的链接和Soren的答案。

0

您是否熟悉C's bitfields?您只需编写

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

被警告,各种操作都在位域慢,因为编译器必须解开他们的东西像加法。我想可以解开一个位域,虽然它需要多条指令,但它仍然会比添加操作本身更快,但它仍然是开销。按位操作应该保持相当快。平等也是如此。

你还必须注意排序和线程(请参阅维基百科的文章我链接的细节,但问题是显而易见的)。无论如何,你应该从字节序列中学习,因为你说“二进制协议”(见this previous questions

+0

或者你真的应该简单地使用协议缓冲包Soren指出。 – 2012-01-17 00:07:35

相关问题