“嗨,阿米戈!”

“我還想談談位掩碼和 XOR。”

“您已經知道數字由位組成,您可以對這些位執行各種操作。位掩碼表示幾個不同的邏輯值(真/假值)作為單個整數。在這種情況下,每個布爾值對應於一個特定的位。這是如何做到的:“

“二(1、2、4、8、16、32,...)的冪的二進製表示只涉及設置一位:”

數字 二進製表示
1個 0000 0001
2個 0000 0010
4個 0000 0100
8個 0000 1000
16 0001 0000
19(不是二的冪) 0001 0011
31(不是二的冪) 0001 1111

“因此,任何整數都可以被視為位數組或布爾值數組。”

“以下是如何在一個數字中存儲不同的布爾值:”

布爾值
boolean a = true;
boolean b = false;
boolean c = true;
boolean d = false;
值打包成一個數字:
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

“現在,如果相應的布爾變量為真,則每一位都為 1。”

在我們的例子中,變量 a 和 c 為真,所以結果等於 1+4 == 5

0000 0101
0000 dcba

“我想我知道發生了什麼。”

“好吧,既然你明白了,那我們就繼續吧。”

“一個int有32位。其中一位用於數字的符號,另外31位可用於存儲31個布爾變量的值。”

“一個 long 有 64 位,我們可以在其中存儲 63 個布爾變量。”

“是的。”

“一個數字裡塞滿了幾十個變數,真是不少啊。”

“但這適用於什麼地方?”

“主要是在你需要存儲大量關於對象的信息的情況下。當你存儲關於一個對象的大量信息時,總會有幾十個布爾變量。“通過這種方法,它們都可以方便地存儲在一個數字中”

“重點放在‘存’字上。因為實際使用這個號碼並不是那麼方便。”

“對了,這正是我想問的。我們如何從數字中提取布爾值?”

“一點都不復雜。假設你需要確定第 6 位是否設置為 1(2 的 5 次方是 32)。我們可以這樣檢查:”

將數字合併為一個:
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

“因此,使用位掩碼涉及三個操作:”

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 是 2 的零次方。換句話說,第 0 位設置為 1 的數字。我們需要第 6 位設置的數字。”

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

“太棒了!這對這種情況真的很有幫助。”

“但是,如果我需要一個數字,其中除了一個特定位設置為 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)”這樣可怕的表達式,你就會知道這個人只是在使用位掩碼。”

“如果你經常遇到它,它就會為你記住自己。”

“記住自己……聽起來不錯。謝謝你的教訓。”