2017-08-10 83 views
0

这段代码是我在用结合4 2位值(无符号的字符,但他们只保持0-3值)到1个单无符号字符值如何将4个2位值合并为1个8位值?

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位值产生相同的结果)。

我很困惑,因为上面的代码是this code的编辑,它可以将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 

我试图改变×03/0x0C /的0x30 /将0xC0到将0xC0 /的0x30/0x0C/0x03时,仍然是错误的。相同更改& 0x03到& 0xC0。

+0

Personnally,我不会打扰做面具的事情,只需直接添加值。代码较大,但如果没有编译器进行大量优化,速度会更快。 第一行:'nibble | = output [i];'第二行:'nibble << = 2;'但是它不应该解决你的问题。 (呵呵,因为问题出在你的=运算符上。) –

回答

5

这是因为你每次都清除半字节中的位。

也就是说,当你这样说:

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)来消灭它们。进一步的细节见this question

+1

如果OP的语句'(无符号字符但它们只保存0-3的值)'被保证,那么'&0x03'的4个实例可以省略。 – Herb

0

这是因为在用新位填充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反正你不需要这个。只需填入Richard's answer中的位即可。

相关问题