2017-08-10 90 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中的位即可。

相關問題