web-dev-qa-db-ja.com

ビットマスキングとは

私はCプログラミングにかなり慣れていない、そして私はビットマスキングに遭遇した。誰かが私にビットマスクの一般的な概念と機能を説明できますか?例は大歓迎です。

137
Mr.Z

マスクはどのビットを保持し、どのビットをクリアするかを定義します。

マスキングは、値にマスクを適用することです。これは次のようにして達成されます。

  • 値内のビットのサブセットを抽出するためのビット単位の論理積
  • 値に含まれるビットのサブセットを設定するためのビット単位の論理和
  • 値の中のビットのサブセットを切り替えるためのビットごとのXOR

以下は、値の中のビットのサブセットを抽出する例です。

Mask:   00001111b
Value:  01010101b

値にマスクを適用するということは、最初の(上位)4ビットをクリアし、最後の(下位)4ビットを保持したいということです。したがって、下位4ビットを抽出しました。年です。結果:

Mask:   00001111b
Value:  01010101b
Result: 00000101b

マスキングはANDを使って実装されているので、Cでは次のようになります。

uint8_t stuff(...) {
  uint8_t mask = 0x0f;   // 00001111b
  uint8_t value = 0x55;  // 01010101b
  return mask & value;
}

これはかなり一般的なユースケースです。より大きなWordから個々のバイトを抽出する。 Wordの上位ビットを最初のバイトとして定義します。これには&>>(右へシフト)という2つの演算子を使います。これが、32ビット整数から4バイトを抽出する方法です。

void more_stuff(uint32_t value) {             // Example value: 0x01020304
    uint32_t byte1 = (value >> 24);           // 0x01020304 >> 24 is 0x01 so
                                              // no masking is necessary
    uint32_t byte2 = (value >> 16) & 0xff;    // 0x01020304 >> 16 is 0x0102 so
                                              // we must mask to get 0x02
    uint32_t byte3 = (value >> 8)  & 0xff;    // 0x01020304 >> 8 is 0x010203 so
                                              // we must mask to get 0x03
    uint32_t byte4 = value & 0xff;            // here we only mask, no shifting
                                              // is necessary
    ...
}

上記の演算子の順序を入れ替えることができます。最初にマスクをしてからシフトを行うことができます。結果は同じですが、今度は別のマスクを使用する必要があります。

uint32_t byte3 = (value & 0xff00) >> 8;
179
user239558

マスキングは、情報の必要な部分を保持/変更/削除することを意味します。画像マスキング操作を見てみましょう。このマスキング操作は肌ではないものを取り除いています。

enter image description here

この例では、および操作をしています。他のマスキング演算子 - またはXまたはもあります。


ビットマスキングは、ビットにマスクをかけることを意味します。これは - によるビットマスキングです。

     1 1 1 0 1 1 0 1   [input]
(&)  0 0 1 1 1 1 0 0    [mask]
------------------------------
     0 0 1 0 1 1 0 0  [output]

したがって、(このマスクではこれらのビットは1であるため)中央の4ビットのみが残ります。

これをXOR - で見てみましょう -

     1 1 1 0 1 1 0 1   [input]
(^)  0 0 1 1 1 1 0 0    [mask]
------------------------------
     1 1 0 1 0 0 0 1  [output]

これで、中央の4ビットが反転しました(10になり、01になりました)。


そのため、ビットマスクを使用して個々のビットにアクセスできます[ examples ]。時々、このテクニックはパフォーマンスを向上させるためにも使われるかもしれません。これを例にとると

bool isOdd(int i) {
    return i%2;
}

この関数は、整数が奇数か偶数かを判断します。ビットマスクを使って同じ結果をより高い効率で達成することができます。

bool isOdd(int i) {
    return i&1;
}

簡単な説明:2進数の 最下位ビット1の場合、それは奇数です。 0の場合は偶数になります。そのため、1を実行することで、最下位ビットを除く他のすべてのビットを削除します。

     55  ->  0 0 1 1 0 1 1 1   [input]
(&)   1  ->  0 0 0 0 0 0 0 1    [mask]
---------------------------------------
      1  <-  0 0 0 0 0 0 0 1  [output]
18
Minhas Kamal