位置:首頁 > 高級語言 > Swift教學 > Swift位運算符

Swift位運算符

位運算符

位操作符通常在諸如圖像處理和創建設備驅動等底層開發中使用,使用它可以單獨操作數據結構中原始數據的比特位。在使用一個自定義的協議進行通信的時候,運用位運算符來對原始數據進行編碼和解碼也是非常有效的。

Swift支持如下所有C語言的位運算符:

按位取反運算符

按位取反運算符~對一個操作數的每一位都取反。

Art/bitwiseNOT_2x.png

這個運算符是前置的,所以請不加任何空格地寫著操作數之前。

let initialBits: UInt8 = 0b00001111
let invertedBits = ~initialBits  // 等於 0b11110000

UInt8是8位無符整型,可以存儲0~255之間的任意數。這個例子初始化一個整型為二進製值00001111(前4位為0,後4位為1),它的十進製值為15

使用按位取反運算~initialBits操作,然後賦值給invertedBits這個新常量。這個新常量的值等於所有位都取反的initialBits,即1變成00變成1,變成了11110000,十進製值為240

按位與運算符

按位與運算符對兩個數進行操作,然後返回一個新的數,這個數的每個位都需要兩個輸入數的同一位都為1時才為1。

Art/bitwiseAND_2x.png

以下代碼,firstSixBitslastSixBits中間4個位都為1。對它倆進行按位與運算後,就得到了00111100,即十進製的60

let firstSixBits: UInt8 = 0b11111100
let lastSixBits: UInt8  = 0b00111111
let middleFourBits = firstSixBits & lastSixBits  // 等於 00111100

按位或運算

按位或運算符|比較兩個數,然後返回一個新的數,這個數的每一位設置1的條件是兩個輸入數的同一位都不為0(即任意一個為1,或都為1)。

Art/bitwiseOR_2x.png

如下代碼,someBitsmoreBits在不同位上有1。按位或運行的結果是11111110,即十進製的254

let someBits: UInt8 = 0b10110010
let moreBits: UInt8 = 0b01011110
let combinedbits = someBits | moreBits  // 等於 11111110

按位異或運算符

按位異或運算符^比較兩個數,然後返回一個數,這個數的每個位設為1的條件是兩個輸入數的同一位不同,如果相同就設為0

Art/bitwiseXOR_2x.png

以下代碼,firstBitsotherBits都有一個1跟另一個數不同的。所以按位異或的結果是把它這些位置為1,其他都置為0

let firstBits: UInt8 = 0b00010100
let otherBits: UInt8 = 0b00000101
let outputBits = firstBits ^ otherBits  // 等於 00010001

按位左移/右移運算符

左移運算符<<和右移運算符>>會把一個數的所有比特位按以下定義的規則向左或向右移動指定位數。

按位左移和按位右移的效果相當把一個整數乘於或除於一個因子為2的整數。向左移動一個整型的比特位相當於把這個數乘於2,向右移一位就是除於2

無符整型的移位操作

對無符整型的移位的效果如下:

已經存在的比特位向左或向右移動指定的位數。被移出整型存儲邊界的的位數直接拋棄,移動留下的空白位用零0來填充。這種方法稱為邏輯移位。

以下這張把展示了 11111111 << 1(11111111向左移1位),和 11111111 >> 1(11111111向右移1位)。藍色的是被移位的,灰色是被拋棄的,橙色的0是被填充進來的。

Art/bitshiftUnsigned_2x.png

let shiftBits: UInt8 = 4   // 即二進製的00000100
shiftBits << 1             // 00001000
shiftBits << 2             // 00010000
shiftBits << 5             // 10000000
shiftBits << 6             // 00000000
shiftBits >> 2             // 00000001

你可以使用移位操作進行其他數據類型的編碼和解碼。

let pink: UInt32 = 0xCC6699
let redComponent = (pink & 0xFF0000) >> 16    // redComponent 是 0xCC, 即 204
let greenComponent = (pink & 0x00FF00) >> 8   // greenComponent 是 0x66, 即 102
let blueComponent = pink & 0x0000FF           // blueComponent 是 0x99, 即 153

這個例子使用了一個UInt32的命名為pink的常量來存儲層疊樣式表CSS中粉色的顏色值,CSS顏色#CC6699在Swift用十六進製0xCC6699來表示。然後使用按位與(&)和按位右移就可以從這個顏色值中解析出紅(CC),綠(66),藍(99)三個部分。

0xCC66990xFF0000進行按位與&操作就可以得到紅色部分。0xFF0000中的0了遮蓋了OxCC6699的第二和第三個字節,這樣6699被忽略了,隻留下0xCC0000

然後,按向右移動16位,即 >> 16。十六進製中每兩個字符是8比特位,所以移動16位的結果是把0xCC0000變成0x0000CC。這和0xCC是相等的,都是十進製的204

同樣的,綠色部分來自於0xCC66990x00FF00的按位操作得到0x006600。然後向右移動8們,得到0x66,即十進製的102

最後,藍色部分對0xCC66990x0000FF進行按位與運算,得到0x000099,無需向右移位了,所以結果就是0x99,即十進製的153

有符整型的移位操作

有符整型的移位操作相對複雜得多,因為正負號也是用二進製位表示的。(這裡舉的例子雖然都是8位的,但它的原理是通用的。)

有符整型通過第1個比特位(稱為符號位)來表達這個整數是正數還是負數。0代表正數,1代表負數。

其餘的比特位(稱為數值位)存儲其實值。有符正整數和無符正整數在計算機裡的存儲結果是一樣的,下來我們來看+4內部的二進製結構。

Art/bitshiftSignedFour_2x.png

符號位為0,代表正數,另外7比特位二進製表示的實際值就剛好是4

負數呢,跟正數不同。負數存儲的是2的n次方減去它的絕對值,n為數值位的位數。一個8比特的數有7個數值位,所以是2的7次方,即128。

我們來看-4存儲的二進製結構。

Art/bitshiftSignedMinusFour_2x.png

現在符號位為1,代表負數,7個數值位要表達的二進製值是124,即128 - 4。

Art/bitshiftSignedMinusFourValue_2x.png

負數的編碼方式稱為二進製補碼表示。這種表示方式看起來很奇怪,但它有幾個優點。

首先,隻需要對全部8個比特位(包括符號)做標準的二進製加法就可以完成 -1 + -4 的操作,忽略加法過程產生的超過8個比特位表達的任何信息。

Art/bitshiftSignedAddition_2x.png

第二,由於使用二進製補碼表示,我們可以和正數一樣對負數進行按位左移右移的,同樣也是左移1位時乘於2,右移1位時除於2。要達到此目的,對有符整型的右移有一個特彆的要求:

對有符整型按位右移時,使用符號位(正數為0,負數為1)填充空白位。

Art/bitshiftSigned_2x.png

這就確保了在右移的過程中,有符整型的符號不會發生變化。這稱為算術移位。

正因為正數和負數特殊的存儲方式,向右移位使它接近於0。移位過程中保持符號會不變,負數在接近0的過程中一直是負數。