「こんにちは、アミーゴ!」

「ビットマスクと XOR についてもお話したいと思います。」

「数値はビットで構成されており、これらのビットに対してさまざまな演算を実行できることはすでにご存知でしょう。ビットマスクは、複数の異なる論理値 (真/偽値) を 1 つの整数として表現したものです。この場合、各ブール値は以下に対応します。特定のビット。これを行う方法は次のとおりです。」

「2 の累乗 (1、2、4、8、16、32、...) のバイナリ表現には、1 ビットの設定だけが必要です。」

番号 バイナリ表現
1 0000 0001
2 0000 0010
4 0000 0100
8 0000 1000
16 0001 0000
19 (2 の累乗ではありません) 0001 0011
31 (2 の累乗ではありません) 0001 1111

「したがって、任意の整数はビットの配列またはブール値の配列として扱うことができます。」

「さまざまなブール値を 1 つの数値に格納する方法は次のとおりです。」

ブール値
boolean a = true;
boolean b = false;
boolean c = true;
boolean d = false;
1 つの数値に詰め込まれた値:
int result = 0;
 if (a) result += 1; // 1 == 20 — bit 0
 if (b) result += 2; // 2 == 21 — bit 1
 if (c) result += 4; // 4 == 22 — bit 2
 if (d) result += 8; // 8 == 23 — bit 3

「対応するブール変数が true の場合、各ビットは 1 になります。」

この場合、変数 a と c は true であったため、結果は 1+4 == 5 と等しくなります。

0000 0101
0000 dcba

「何が起こっているかはわかっていると思います。」

「まあ、わかったら次に進みましょう。」

「int には 32 ビットがあります。そのうちの 1 つは数値の符号に使用され、残りの 31 は 31 個のブール変数の値を格納するために使用できます。」

「long には 64 ビットがあり、そこに 63 個のブール変数を格納できます。」

「はい。」

「1 つの数値に数十の変数が詰め込まれています。それはかなりの数です。」

「しかし、これはどこに適用されるのでしょうか?」

「主に、オブジェクトに関する多くの情報を保存する必要がある状況で使用されます。オブジェクトに関する多くの情報を保存する場合、常に数十個のブール変数が存在します。」このアプローチを使用すると、それらはすべて 1 つの数値に保存されるので便利です。 。」

「『保管されている』という言葉を強調しています。実際に番号を使用するのはそれほど便利ではないからです。」

「ところで、それが聞きたかったことなのですが、数値からブール値を取り出すにはどうすればよいでしょうか?」

「まったく複雑ではありません。ビット 6 が 1 (2 の 5 乗は 32) に設定されているかどうかを判断する必要があるとします。次のように確認できます。」

数値を 1 つに結合します。
int a = 32; // 25 == 0010 0000
int b = 8; // 23 == 0000 1000
int c = 2; // 21 == 0000 0010

int result = a + b + c; // 32 + 8 + 2 == 42 == 0010 1010
特定のビットをチェックして値を抽出します。
int a = result & 32; // 0010 1010 & 0010 0000 = 0010 0000
int b = result & 8; // 0010 1010 & 0000 1000 = 0000 1000
int c = result & 2; // 0010 1010 & 0000 0010 = 0000 0010

「したがって、ビットマスクの操作には 3 つの操作が必要です。」

1) 特定のビットを 0 に設定する

2) 特定のビットを 1 に設定します

3) 特定のビットの値を確認します。

「たとえば、ビット 6 を考えてみましょう。」

「ビット 6 を 1 に設定するにはどうすればよいですか?」

コード 説明
result = result | 01000000;
result |= 01000000;
ビット6を1に設定するにはどうすればよいですか?
result = result & 10111111;
result &= 10111111;
ビット6を0に設定するにはどうすればよいですか?
c = result & 01000000;
ビット6の値はどうやって取得するのでしょうか?

「それは非常に珍しいことですが、難しいことではありません。まあ、今では私は売れっ子のプログラマーです。」

「そして、特定のビットが 0 または 1 に設定された数値 (01000000 または 10111111) を簡単に取得する方法に関する小さなヒントがもう 1 つあります。」

このために、 >>演算子と <<演算子があります 

「1 は 2 の 0 乗です。つまり、ビット 0 が 1 に設定された数値です。ビット 6 が設定された数値が必要です。」

int c = 1 << 6; // 0000 0001 << 6 == 0100 0000 == 64

「すごいですね!こういう場合には本当に助かります。」

「しかし、特定の 1 つのビットが 0 に設定されている以外のすべてのビットが 1 に設定されている数値が必要な場合はどうすればよいでしょうか?」

「それも難しいことではありません。」

int d = ~(1 << 6); // ~0100 0000 == 10111111

「言い換えれば、すべては非常に簡単です。」

コード 説明
result = result | (1 << 6);
result |= (1 << 6);
ビット6を1に設定するにはどうすればよいですか?
result = result & ~(1 << 6);
result &= ~(1 << 6);
ビット6を0に設定するにはどうすればよいですか?
c = result & (1 << 6);
ビット6の値はどうやって取得するのでしょうか?

「そんなに難しくなさそうだけど、すぐには覚えられないよ」

「しかし、他の人のコードで「result &= ~(1 << 6)」のような恐ろしい表現に遭遇した場合、その人がビットマスクを操作しているだけであることがわかります。」

「そして、あなたが頻繁にそれに遭遇すると、それはあなたのためにそれ自身を覚えてくれるでしょう。」

「覚えておいてください...それはいいですね。レッスンをありがとう。」