2016-09-07 12 views
4

Iは、それらの値が0である場合、2ビット(例えばビット数3,5)UINT8 の値を確認したい、私は1ビット値検証

uint8 a; 
if ((a & !(1<<3)) && (a & !(1<<5))) 
{ 
    Instructions.. 
} 

を返すようにしたい、このコードは正しいです?

+3

いいえ、 'a'は初期化されていないためです。 –

+1

ビットの否定は '〜'ではありません! – LPs

+2

質問する前にいくつかのテストを行い、すぐにこの条件が正しくないことがわかります。 – MikeCAT

答えて

0

a実際にに初期化されていると仮定すると、期待どおりに式が機能しません。論理非演算子!は1または0(真または偽のブール値)を与え、ビット単位および演算で使用します。それはあなたに正しい結果を与えません。

~(1 << 3)のように、ビット補数演算子~を代わりに使用するとします。とにかく、それはちょうどaの他のビットのどれかが非ゼロであることをチェックするので、それはとにかく動作しません。

ビットが1であるかどうかを確認して、!(a & 1 << 3)のように、演算子ではない論理!を使用してロジックを回してください。

1

正しくありません。

!演算子はブール値ではなく、ビット単位ではありません。あなたはビット3 & 5は両方ともゼロにしているかどうかを確認したい場合は

だから、あなたが書く必要があります:if中での発現の

uint8 a; 
... 
if (!(a & (1<<3)) && !(a & (1<<5))) 
{ 
    Instructions.. 
} 

さらなる最適化が可能です。

0

あなたの表現は偽です。このようにマスクを否定してはならないので、他のビットを無視してネゲーションを使わないでください。単純に:

(a & (1<<3)) + (a & (1<<5)) 

は、両方が0の場合は0を返します。

0

!演算子は論理否定を行い、1<<3はゼロではないため、!(1<<3)はゼロです。つまり、a & !(1<<3)は常にゼロになるため、条件は決して真ではありません。

マスキングは、あなたがしたいことをする良い方法の1つだと思います。

uint8 a; 
/* assign something to a */ 
return (a & ((1 << 3) | (1 << 5))) == 0; 

a & ((1 << 3) | (1 << 5))は、第3及びaの5ビット目(0原点)が、それらの元の値を維持し、他のすべてのビットがゼロになった値です。値がゼロであるかどうかをチェックすることは、検査すべきビットがすべてゼロであるか否かをチェックし、他のビットは考慮しないことを意味する。 ==オペレータは、2つのオペランドが等しい場合は1を返し、そうでない場合は0を返します。

4

いいえ、あなたのコードは、あなたが望むように動作しません。 !演算子の結果は0またはで、実際の非ゼロビットに関する情報はとにかく失われます。あなたは|演算子でマスクを作成している最初の段階では

if(!(a & ((1 << 3) | (1 << 5))) { 
    /* ... */ 
} 

:あなたはこのようなものを使用することができます。このマスクはあなたが興味を持っている位置にのみゼロ以外のビットを持っています。そして、このマスクは&によってテストされた値と組み合わされます。結果として、値がゼロのビットがテスト済みの位置にある場合にのみ0が得られます。そして真の状態を得るために逆01!と反転するだけです。

1

これは、1つのわかりにくい表現として書き込もうとしないと簡単です。そうすることの利点はありません - 一般的な考え方とは反対に、多くの演算子を1行にまとめることは、実際には非常に悪い習慣です。読みやすさが損なわれ、パフォーマンス上のメリットはありません。だから、ビットマスク作成から始め

uint8_t mask = (1<<3) | (1<<5); 

を(カッコは実際に必要とされるのではなく、誰もが自分の睡眠中にCの演算子の優先順位表を引用することができますので、これはお勧めスタイルです。)

その後、マスクに対してデータをチェック:

あなたは、ブール式のように書き換えることができます場合は、
if(data & mask) // if any bit contains value 1 
    return 0; 
else   // if no bit contains value 1 
    return 1; 

return !(data & mask); 

完全な機能は次のようになります。あなたには、いくつかのBIT_ABIT_Bの組み合わせ(またはあなたが持つことができますビットのどんな数)をテストしたい場合は

bool check_bits (uint8_t data) 
{ 
    uint8_t mask = (1<<3) | (1<<5); 
    return !(data & mask); 
} 
0

あなたがこれを行うことができます:

#define BIT_A (1 << 3) 
#define BIT_B (1 << 5) 
... 
#define BIT_Z (1 << Z) 

... 
/*  |here you put all bits   |here you put only the ones you want set */ 
/*  V        V            */ 
if (a & (BIT_A | BIT_B | ... | BIT_Z) == (BIT_A | ... | BIT_I | ...)) 
{ 
    /* here you will know that bits BIT_A,..., BIT_I,... will **only** 
    * be set in the mask of (BIT_A | BIT_B | ... | BIT_Z) */ 
} 

a & (BIT_A | BIT_B | ...)のように、セット内のすべてのビットがゼロになるように強制すると、セット内のビットだけが値を保存します。 2番目のマスクでは、設定したいビットのセットだけをビットマップで生成します(もちろん、セットに含まれていないビットはゼロになります)。両方の値を等価で比較すると、期待される結果。

あなたの質問への答えとして

NOTEは、あなたが1に等しいすべてのビットを望んでいる特定のケースでは、両方のマスクが同じようにすることです。あなたのケースでは、あなたが両方のビットがゼロあるかどうかを確認したい、そして、あなたのテストは(それがゼロであるように、第2のマスクは、設定何のビットを持っていない)されています

if (a & ((1 << 3) | (1 << 5)) == 0) { ... 

(第2のマスクのすべてのビットであります必要なマスクとの両方、第3及び第5ビットは、第一のマスクに設定されているようなゼロ)これは(あなたがそれのように書かれて見ることができる)、よりコンパクトな形式で書くことができる。

if (!(a & 0x28)) { /* 0x28 is the octal for 00101000, with the bits you require */ 

なぜコードが正しくありません

まず、logi !のようなビット演算子を0(と異なるので、それは真であり、否定すると0となる)と!(1<<5)部分式の場合と同じになるように、ビットマスクを用いて!(1<<3)を評価する。これらの値でマスクすると、a & 0 ==> 0a & 0 ==> 0が得られ、両方を合わせると0 && 0 ==> 0となります。したがって、式の結果値は、の元の値とは関係なく、常に0 -- falseです。