繁体   English   中英

如何将4个2位值组合为1个8位值?

[英]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.cppg++ -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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM