![](/img/trans.png)
[英]How to advance in a queue with 8-bit members and combine couples into 16-bit values
[英]How do I combine 4 2-bit values into 1 8-bit value?
这段代码是我用来将4个2位值(无符号字符,但它们仅包含0-3的值)组合成1个单个无符号字符值的功能
unsigned char nibble = 0;
nibble = (nibble & 0x03) | (output[i] & 0x03);
nibble = (nibble & 0x0C) | (output[i+1] & 0x03) << 2);
nibble = (nibble & 0x30) | (output[i+2] & 0x03) << 4);
nibble = (nibble & 0xC0) | (output[i+3] & 0x03) << 6);
对于除00 00 00 00之外的所有值,它都会产生错误的值(对于两组2位不同的2位值,通常会产生相同的结果)。
我很困惑,因为上面的代码是对该代码的编辑,可以很好地将2个4位值合并为1个字节,为什么我的版本不将4个2位值合并为1个字节?
char byte;
byte = (byte & 0xF0) | (nibble1 & 0xF); // write low quartet
byte = (byte & 0x0F) | ((nibble2 & 0xF) << 4); // write high quartet
我尝试将0x03 / 0x0C / 0x30 / 0xC0更改为0xC0 / 0x30 / 0x0C / 0x03,仍然是错误的。 将&0x03更改为&0xC0时相同。
这是因为您每次都清除半字节中的位。
也就是说,当您这样说:
nibble = (nibble & 0xC0)
您真正要说的是“放弃到目前为止我已经完成的所有工作,除了位置3和4的钻头”。
此代码(未经测试)可能会解决您的问题:
unsigned char nibble = 0;
nibble |= (output[i ] & 0x03);
nibble |= (output[i+1] & 0x03) << 2;
nibble |= (output[i+2] & 0x03) << 4;
nibble |= (output[i+3] & 0x03) << 6;
如果确实确实output[i+x]
仅保存[0,3]范围内的值,则可以如下更改代码:
unsigned char nibble = 0;
assert(0<=output[i ] && output[i ]<=3)
nibble |= output[i ];
assert(0<=output[i+1] && output[i+1]<=3)
nibble |= output[i+1] << 2;
assert(0<=output[i+2] && output[i+2]<=3)
nibble |= output[i+2] << 4;
assert(0<=output[i+3] && output[i+3]<=3)
nibble |= output[i+3] << 6;
如果您确实非常确定,那么可以断言断言。 但是,您也可以保留它们,让编译器使用NDEBUG
标志( g++ -DNDEBUG mycode.cpp
) g++ -DNDEBUG mycode.cpp
。 有关更多详细信息,请参见此问题 。
那是因为在用新位填充nibble
之前,您要先用一个掩码过滤它,如果有什么事情与它应该做的相反。
nibble = (nibble & 0x03) | (output[i] & 0x03);
nibble = (nibble & 0x0C) | (output[i+1] & 0x03) << 2);
nibble = (nibble & 0x30) | (output[i+2] & 0x03) << 4);
nibble = (nibble & 0xC0) | (output[i+3] & 0x03) << 6);
^^^^ in here you preserve the bits
you want to replace and zero out everything else
反转该掩码将起作用:
nibble = (nibble & ~0x03) | (output[i] & 0x03);
nibble = (nibble & ~0x0C) | (output[i+1] & 0x03) << 2);
nibble = (nibble & ~0x30) | (output[i+2] & 0x03) << 4);
nibble = (nibble & ~0xC0) | (output[i+3] & 0x03) << 6);
但是,由于nibble
无论如何已经从0
开始,所以您不需要它。 就像在理查德的答案中那样填充位。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.