web-dev-qa-db-ja.com

ビットマスクの使用方法は?

C++で使用するにはどうすればよいですか?いつ使用すると便利ですか?
ビットマスクが使用されている場合の問題の例を教えてください。ありがとう!

52
Animea Animea

ビットマスキングは、単一のデータ値内に異なるデータを格納(および抽出)するときに使用すると「便利」です。

以前に使用したサンプルアプリケーションは、カラーRGB値を16ビット値で保存していると想像してください。このように見えるもの:

RRRR RGGG GGGB BBBB

次に、ビットマスキングを使用して、次のように色成分を取得できます。

  const unsigned short redMask   = 0xF800;
  const unsigned short greenMask = 0x07E0;
  const unsigned short blueMask  = 0x001F;

  unsigned short lightGray = 0x7BEF;

  unsigned short redComponent   = (lightGray & redMask) >> 11;
  unsigned short greenComponent = (lightGray & greenMask) >> 5;
  unsigned short blueComponent =  (lightGray & blueMask);
31
Dutts

簡単に言うと、ビットマスクは複数の値の位置を操作するのに役立ちます。ここに良い例があります。

ビットフラグは、相互に排他的ではない複数の値を1つの変数に格納する方法です。おそらく前に見たことがあるでしょう。各フラグは、オンまたはオフに設定できるビット位置です。その後、ビット位置ごとに#definedのビットマスクの束を定義して、簡単に操作できるようにします。

    #define LOG_ERRORS            1  // 2^0, bit 0
    #define LOG_WARNINGS          2  // 2^1, bit 1
    #define LOG_NOTICES           4  // 2^2, bit 2
    #define LOG_INCOMING          8  // 2^3, bit 3
    #define LOG_OUTGOING         16  // 2^4, bit 4
    #define LOG_LOOPBACK         32  // and so on...

// Only 6 flags/bits used, so a char is fine
unsigned char flags;

// initialising the flags
// note that assigning a value will clobber any other flags, so you
// should generally only use the = operator when initialising vars.
flags = LOG_ERRORS;
// sets to 1 i.e. bit 0

//initialising to multiple values with OR (|)
flags = LOG_ERRORS | LOG_WARNINGS | LOG_INCOMING;
// sets to 1 + 2 + 8 i.e. bits 0, 1 and 3

// setting one flag on, leaving the rest untouched
// OR bitmask with the current value
flags |= LOG_INCOMING;

// testing for a flag
// AND with the bitmask before testing with ==
if ((flags & LOG_WARNINGS) == LOG_WARNINGS)
   ...

// testing for multiple flags
// as above, OR the bitmasks
if ((flags & (LOG_INCOMING | LOG_OUTGOING))
         == (LOG_INCOMING | LOG_OUTGOING))
   ...

// removing a flag, leaving the rest untouched
// AND with the inverse (NOT) of the bitmask
flags &= ~LOG_OUTGOING;

// toggling a flag, leaving the rest untouched
flags ^= LOG_LOOPBACK;



**

警告:フラグが設定されているかどうかをテストするために等値演算子(ビットフラグ==ビットマスク)を使用しないでください。フラグが設定され、他のすべてが設定されていない場合にのみ式が真になります。単一のフラグをテストするには、&と==を使用する必要があります。

**

if (flags == LOG_WARNINGS) //DON'T DO THIS
   ...
if ((flags & LOG_WARNINGS) == LOG_WARNINGS) // The right way
   ...
if ((flags & (LOG_INCOMING | LOG_OUTGOING)) // Test for multiple flags set
         == (LOG_INCOMING | LOG_OUTGOING))
   ...

C++ Triks を検索することもできます

102
goGud

チャンネルごとに8ビットの32ビットARGB値があるとします。アルファコンポーネントを0x45などの別のアルファ値に置き換えたい

unsigned long alpha = 0x45
unsigned long pixel = 0x12345678;
pixel = ((pixel & 0x00FFFFFF) | (alpha << 24));

マスクは、古いアルファ値があった上位8ビットを0に変更します。アルファ値は、取得する最終ビット位置までシフトされ、マスクされたピクセル値にOR演算されます。最終結果は0x45345678で、ピクセルに保存されます。

3
Neil Kirk

ビットマスクは、情報の複数のレイヤーを単一の数値にエンコードする場合に使用されます。

そのため(UNIXファイルのアクセス許可を想定)、3レベルのアクセス制限(読み取り、書き込み、実行)を保存する場合、対応するビットをチェックすることで各レベルをチェックできます。

rwx
---
110

ベース2の110は、ベース10の6に変換されます。

だから、誰かが許可されているかどうかを簡単に確認できます目的の許可を使用して許可フィールドにandを実行してファイルを読み取ります。

擬似コード:

PERM_READ = 4
PERM_WRITE = 2
PERM_EXEC = 1

user_permissions = 6

if (user_permissions & PERM_READ == TRUE) then
  // this will be reached, as 6 & 4 is true
fi

ビットフィールドを理解するには、数値のバイナリ表現と論理演算子の実用的な理解が必要です。

3
til_b