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

Storing 3 different values in a single byte

我正在使用专有的二进制消息传递协议,在一条消息中,一个字节用于存储 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);             
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