ビットマスキングとは何ですか?


191

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


1
&|などのビット演算子を理解していますか?^ etcとブール論理一般?マスク操作の説明では、これが必要になります。
ポールR

1
はい、ビットごとの演算子とブール論理について理解しています
Mr.Z、2012年

2
リンクが投稿されるべきではないことは知っていますが、ウィキペディアの説明はすばらしいです:en.wikipedia.org/wiki/Mask_
computing

2
@pevikリンクを投稿しても大丈夫ですが、リンクがいつか死んだ場合でも、投稿が回答の目的を果たすことができるように、いくつかの説明が含まれています。また、リンクは単なる宣伝目的であってはなりません。
デクスター

回答:


243

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

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

  • 値のビットのサブセットを抽出するためのビットごとのAND演算
  • 値にビットのサブセットを設定するためのビット単位のOR演算
  • 値のビットのサブセットを切り替えるためのビット単位の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;
}

これはかなり一般的なユースケースです:大きなワードから個々のバイトを抽出します。ワードの上位ビットを最初のバイトとして定義します。これには&、と>>(右シフト)の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;

5
正解ですが、ORまたはXOR演算と適切なマスクを使用して特定のビットを設定またはトグルするためにマスキングを適用することもできます。
Paul R

@ user239558例と適切な構文に感謝します。ポール・R.でしょう私は単にuser239558によって提供された例ではマスクと値を言う@
Mr.Z

@ Mr.Z:C、C ++および関連言語では、ビット単位のAND演算子を使用し&ます。
ポールR

@ Mr.Z例:内容をマスキングしてuint32_tの1バイトをクリアします#define MASK 0x000000FF .... my_uint32_t &= ~MASK
ランディン

bバイナリリテラルを示すためには、正しいすべてのコンパイラでサポートされていませんか?
Ungeheuer 2017年

76

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

ここに画像の説明を入力してください

この例では、AND演算を行っています。他のマスキング演算子-ORXORもあります。


ビットマスキングとは、ビットにマスクを課すことを意味します。ここにANDを使用したビットマスキングがあります-

     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]

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

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ビットが反転している(1となった00となりました1)。


したがって、ビットマスクを使用して、個々のビットにアクセスできます[ ]。場合によっては、この手法を使用してパフォーマンスを向上させることもできます。これを例にとると

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]

1
また、整数を奇数に変換します。偶数の場合:i = i | 1。これは、
1、3、5

次の演算を使用して、整数から最下位ビットのみの数値を見つけることもできます
。lsb
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.