【位運算經典應用】 標志位與掩碼


前面我們已經了解了六大位操作符(& | ~ ^ << >>)的用法(javascript 位運算),也整理了一些常用的位運算操作(常用位運算整理),本文我們繼續深入位運算,來了解下二進制的經典應用-標志位與掩碼。

位運算經常被用來創建、處理以及讀取標志位序列——一種類似二進制的變量。雖然可以使用變量代替標志位序列,但是這樣可以節省內存(1/32)。

例如有4個標志位:

  1. 標志位A: 我們有 orange
  2. 標志位B: 我們有 apple
  3. 標志位C: 我們有 banana
  4. 標志位D: 我們有 pear

標志位通過位序列DCBA來表示,當一個位置被置為1時,表示有該項,置為0時,表示沒有該項。例如一個變量flag=9,二進制表示為1001,就表示我們有D和A。

掩碼 (bitmask) 是一個通過與/或來讀取標志位的位序列。典型的定義每個標志位的原語掩碼如下:

var FLAG_A = 1; // 0001
var FLAG_B = 2; // 0010
var FLAG_C = 4; // 0100
var FLAG_D = 8; // 1000

新的掩碼可以在以上掩碼上使用邏輯運算創建。例如,掩碼 1011 可以通過 FLAG_A、FLAG_B 和 FLAG_D 邏輯或得到:

var mask = FLAG_A | FLAG_B | FLAG_D; // 0001 | 0010 | 1000 => 1011

某個特定的位可以通過與掩碼做邏輯與運算得到,通過與掩碼的與運算可以去掉無關的位,得到特定的位。例如,掩碼 0100 可以用來檢查標志位 C 是否被置位:(核心就是判斷某位上的數 參考常用位運算整理 下同)

// 如果我們有 banana
if (flags & FLAG_C) { // 0101 & 0100 => 0100 => true
   // do stuff
}

一個有多個位被置位的掩碼表達任一/或者的含義。例如,以下兩個表達是等價的:

// 如果我們有 apple 或者 banana 至少一個
// (0101 & 0010) || (0101 & 0100) => 0000 || 0100 => true
if ((flags & FLAG_B) || (flags & FLAG_C)) {
   // do stuff
}

var mask = FLAG_B | FLAG_C; // 0010 | 0100 => 0110
if (flags & mask) { // 0101 & 0110 => 0100 => true
   // do stuff
}

可以通過與掩碼做或運算設置標志位,掩碼中為 1 的位可以設置對應的位。例如掩碼 1100 可用來設置位 C 和 D:(核心就是將某位變為1

// 我們有 banana 和 pear
var mask = FLAG_C | FLAG_D; // 0100 | 1000 => 1100
flags |= mask;   // 0101 | 1100 => 1101

可以通過與掩碼做與運算清除標志位,掩碼中為 0 的位可以設置對應的位。掩碼可以通過對原語掩碼做非運算得到。例如,掩碼 1010 可以用來清除標志位 A 和 C :(核心就是將某位變為0

// 我們沒有 orange 也沒有 banana
var mask = ~(FLAG_A | FLAG_C); // ~0101 => 1010
flags &= mask;   // 1101 & 1010 => 1000

如上的掩碼同樣可以通過 ~FLAG_A & ~FLAG_C 得到(德摩根定律):

// 我們沒有 orange 也沒有 banana
var mask = ~FLAG_A & ~FLAG_C;
flags &= mask;   // 1101 & 1010 => 1000

標志位可以使用異或運算切換。所有值為 1 的為可以切換對應的位。例如,掩碼 0110 可以用來切換標志位 B 和 C:(核心就是將某位取反

// 如果我們以前沒有 apple ,那么我們現在有 apple
// 但是如果我們已經有了一個,那么現在沒有了
// 對 banana 也是相同的情況
var mask = FLAG_B | FLAG_C;
flags = flags ^ mask;   // 1100 ^ 0110 => 1010

最后,所有標志位可以通過非運算翻轉:

// entering parallel universe...
flags = ~flags;    // ~1010 => 0101


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM