2017-08-10 7 views
0

このコードは、私は4の2ビットの値を結合する(符号なし文字をしかし、彼らは唯一の0-3からの値を保持)するために使用しています何である1つのunsigned char型の値に変換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組の2ビット値について同じ結果を生成することが多い)。

上記のコードは2つの4ビット値を1つのバイトに結合するようにうまく動作するthis codeの編集ですので、混乱します。なぜ私のバージョンでは4つの2ビット値を1バイトに結合しませんか?

char byte; 
byte = (byte & 0xF0) | (nibble1 & 0xF); // write low quartet 
byte = (byte & 0x0F) | ((nibble2 & 0xF) << 4); // write high quartet 

私はまだ間違って、0xC0の/ 0x30から/ 0x0Cの/ 0x03のに0x03を/ 0x0Cの/ 0x30から/ 0xC0の変更を試してみました。 & 0x03から& 0xC0に変更する場合と同じです。

+0

個人的には、マスクのことを気にせずに値を直接追加するだけです。コードは大きくなりますが、多くの最適化を行うコンパイラがない場合は速くなります。 最初の行: 'nibble | = output [i];' 2行目: '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のようにビットを入力してください。

関連する問題