在单个字节中存储3个不同的值

时间:2015-04-16 13:50:37

标签: c# bit-manipulation

我正在使用专有的二进制消息传递协议,在一条消息中,一个字节用于存储3个不同的值,如下所示:

Bit
7   IsArray (1 bit)
6   ArrayLength, MSB (4 bits, max size 2^4 = 16)
5
4
3
2   DataType, MSB (3 bits, max size = 2^3 = 8)
1
0

我想提取这三个值,并将它们存储在对象bool IsArraybyte ArrayLengthbyte DataType中的三个不同属性中。我还需要从这三个属性返回到单个字节

我很少在这个级别上工作,当我超越设置或获得IsArray的单个位,尝试同时设置几个时,事情变得有点混乱。我创造了三种不同的面具,我认为这会对我有所帮助:

var IsArrayMask = 0x80;     // 1000 0000
var ArrayLengthMask = 0x78; // 0111 1000
var DataTypeMask = 0x07;    // 0000 0111

有没有一种优雅的方式来实现我的目标?

编辑:在@stefankmitph的帮助下,我发现我的变速都搞砸了。这就是我现在从3个属性转到单个字节的方式:

bool IsArray = true;
byte ArrayLength = 6;
byte DataType = 3;

byte serialized = 0x00; // Should end up as 1011 0011 / 0xB3

serialized |= (byte)((IsArray ? 1 : 0) << 7 & IsArrayMask);
serialized |= (byte)(ArrayLength << 3 & ArrayLengthMask);
serialized |= (byte)(DataType & DataTypeMask);

再回来,根据以下答案:

bool isArray = (serialized & IsArrayMask) == IsArrayMask; 
int arrayLength = (serialized & ArrayLengthMask) >> 3;  
int dataType = (serialized & DataTypeMask);             

1 个答案:

答案 0 :(得分:3)

int val = 0xBE;  //f.e. 1011 | 1110
var IsArrayMask = 0x80;     // 1000 0000
var ArrayLengthMask = 0x78; // 0111 1000
var DataTypeMask = 0x07;    // 0000 0111

bool isArray = ((val & IsArrayMask) >> 7) == 1;  // output: true

// as pointed out by @PeterSchneider & @knittl 
// you can get isArray in a probably more elegant way:
isArray = (val & IsArrayMask) == IsArrayMask;

// i keep both ways in my answer, because i think 
// the first one illustrates that you have to shift by 7 to get 1 (true) or 0 (false) 

int arrayLength = (val & ArrayLengthMask) >> 3;  // output: 7
int dataType = (val & DataTypeMask);             // output: 6