1、概述
除了一些基本的操作符,Swift提供了幾種能夠執行更加復雜值操縱的高級操作符。其中包括你所熟悉的C和OC中的按位位移操作符。
與C語言的算數運算符不同,Swift中的算數操作符默認不會溢出(overflow)。溢出行為被捕獲并且作為一個錯誤被報告。如果要參與溢出行為,使用Swift的默認會溢出的第二套算數操作符,例如溢出加(&+)。Swift中的會溢出的操作符都以&開頭。
Swift允許為你自定義的類型提供自己的標準操作符實現。
Swift允許自由的定義你自己的自定義的中綴,前綴,后綴,賦值操作符,以及自定義的優先級和結合律。并且你可以擴展已存在的類型來支持你定義的自定義操作符。
2、位操作符
位操作符允許操縱數據結構中的獨立的原始數據位。常用于低級別的程序,例如圖形程序和設備驅動創建。當你工作于來自外部源的原始數據,例如通過自定義協議交流的數據的編解碼,位操作符也是很有用的。
1)位NOT操作符(~),翻轉一個數字中的所有位。前綴操作符,直接在值的前面,沒有空格
例:let initialBits: UInt8 = 0b00001111
? ? ? ?let invertedBits = ~initialBits ? ? //等于11110000
2)位AND操作符。從兩個被操作數返回一個新的值,只有兩個被操作數對應位都為1,返回值的對應位才為1.
例: let firstSixBits: UInt8 = 0b11111100
? ? ? ? let lastSixBits: UInt8 = 0b00111111
? ? ? ? let middleFourBits = firstSixBits & lastSixBits //等于0b00111100
3)位OR操作符。從兩個被操作數返回一個新的值,只要兩個被操作數對應位任意一個為1,返回值的對應位就為1.
例:let someBits: UInt8 = 0b10110010
? ? ? ?let moreBits: UInt8 = 0b01011110
? ? ? ?let combinedbits = someBits | moreBits //等于0b11111110
4)位XOR操作符。異或操作符(^)。操作符返回一個新的值,返回值的每一位是:被操作的兩個數對應位不相同返回1,相同返回0
例:let firstBits: UInt8 = 0b00010100
? ? ? ?let otherBits: UInt8 = 0b00000101
? ? ? ?let outputBits = firstBits ^ otherBits //等于0b00010001
5)按位左移和右移操作符。邏輯位移(logic shift)。按位左移(<<)有乘以2的效果,按位右移(>>)有除以2的效果。
無符號整數的移位行為:
(1)存在的位被左移或者右移相應的位數
(2)移動之后超出整數存儲范圍的位拋棄
(3)原始位左移右移之后空出的位置0
例:let shiftBits: UInt8 = 4 ?// 00000100 in binary
? ? ? ?shiftBits << 1 ?// 00001000
? ? ? ?shiftBits << 2 ?// 00010000
? ? ? ?shiftBits << 5 ?// 10000000
? ? ? ?shiftBits << 6 ?// 00000000
? ? ? ?shiftBits >> 2 ?// 00000001
有符號整數的位移行為:有符號整數使用第一位標明整數是正(0)的還是負(1)的。剩余的為存儲實際的值。
正整數存儲于無符號整數相同,除了最高位為0,代表是正值:
負整數存儲有一些不同。它們存儲的是2的n次方減去它的絕對值,其中n代表值的位數。一個8位數有7位值位:
這種負數編碼方式叫做二進制補碼(two's complement)。這種表示方法有幾個好處:
(1)加法運算。如-1+-4。只需要執行標準的8位二進制加法即可,拋棄任何超出的部分
(2)負數的位移操作和正數位移得以統一。有一個規則:當你右移有符號整數,規則與無符號整數一樣,只是填充空余位為標志位而不是0。這樣保證了右移之后符號位相同,被稱為算術位移(arithmetic shift)
2、溢出操作符
如果你試圖給一個不能保留這個值的整形常量或變量插入一個值,默認情況下,Swift報一個錯誤,而不是允許一個無效的值被創建。這個行為保證了安全性。超出范圍的賦值會引起錯誤:
var potentialOverflow = Int16.max
// potentialOverflow等于32767, Int16的最大值
potentialOverflow+=1
// Error
當你特別的需要溢出條件來階段可用位的數字,Swift提供三種算術溢出操作符,允許整數計算的溢出行為。這些操作符都以&開頭:
Overflow addtion (&+)
Overflow subtraction (&-)
Overflow multiplication (&*)
1)值溢出。數字可以在正數和負數兩個方向都溢出。例:
var unsignedOverflow = UInt8.max
// unsignedOverflow 等于255, UInt8的最大值
unsignedOverflow=unsignedOverflow&+1
// unsignedOverflow現在等于0
var unsignedOverflow = UInt8.min
// unsignedOverflow等于0, UInt8最小值
unsignedOverflow = unsignedOverflow&-1
// unsignedOverflow等于255
有符號整數的溢出計算,符號位也作為加減數字的一部分來計算。例:
var signedOverflow=Int8.min
// signedOverflow等于-128, Int8的最小值
signedOverflow=signedOverflow&-1
// signedOverflow等于127
對于有符號和無符號整數,正方向的溢出計算回環從最大有效值到最小有效值。負方向的溢出計算回環從最小有效值到最大有效值。
3、優先級和結合律
操作符優先級使得一些操作符比其他操作符有更高的優先級,優先級高的先實施。操作符結合律定義了同一優先級的操作符怎么來組合。操作符優先級解釋了以下表達式等于17:
2 + 3 % 4 * 5
高優先級的操作符比低優先級的先計算。而同一級別優先級操作符哪個先計算由結合律來確定,等同于隱式的添加了括號:
2 + ((3 % 4)* 5)
4、操作符方法(operator methods)
類和結構體可以提供已存在操作符的自己的實現,這成為操作符重載(overloading the existing operators)。下面的例子實現了結構體內算法加操作符,二元中綴操作符(binary infix operator):
struct Vector2D{
? var x=0.0,y=0.0
}
extension Vector2D{
? ? static func + (left:Vector2D,right:Vector2D) ->Vector2D{
? ? ? ? returnVector2D(x:left.x+right.x,y:left.y+right.y)
? ? }
}
let vector = Vector2D(x:3.0,y:1.0)
let anotherVector = Vector2D(x:2.0,y:4.0)
let combinedVector = vector+anotherVector
// combinedVector is a Vector2D instance with values of (5.0, 5.0)
前綴和后綴操作符。通過在func關鍵字前面寫prefix和postfix來實現前綴或者后綴一元操作符:
extension Vector2D{
? ? static prefix func - (vector:Vector2D) ->Vector2D{
? ? ? ? returnVector2D(x: -vector.x,y: -vector.y)
? ? }
}
let positive=Vector2D(x:3.0,y:4.0)
let negative= -positive
// negative is a Vector2D instance with values of (-3.0, -4.0)
let alsoPositive= -negative
// alsoPositive is a Vector2D instance with values of (3.0, 4.0)
混合的賦值操作符(compound assignment operators)。其方法重載需標記左輸入參數類型為inout。例:
extension Vector2D{
? ? static func += (left:inoutVector2D,right:Vector2D) {
? ? ? ? left=left+right
? ? }
}
var original = Vector2D(x:1.0,y:2.0)
let vectorToAdd = Vector2D(x:3.0,y:4.0)
original += vectorToAdd
// original now has values of (4.0, 6.0)
賦值操作符和三元條件操作符不能被重載(overload)
相等操作符(equivalence operators)。為自定義類型實現相等操作符實現與其他中綴操作符一樣。例:
extension Vector2D{
? ? static func ==? (left:Vector2D,right:Vector2D) ->Bool{
? ? ? ? return(left.x==right.x) && (left.y==right.y)
? ? }
? ? static func !=? (left:Vector2D,right:Vector2D) ->Bool{
? ? ? ? return!(left==right)
? ? }
}
let twoThree = Vector2D(x:2.0,y:3.0)
let anotherTwoThree = Vector2D(x:2.0,y:3.0)
if twoThree == anotherTwoThree{
? ? print("These two vectors are equivalent.")
}
// Prints "These two vectors are equivalent."
5、自定義操作符
新的操作符聲明在一個全局級別,使用operator關鍵字,并且以prefix、infix、postfix做修飾符。例:
extension Vector2D{
? ? static prefix func +++ (vector:inoutVector2D) ->Vector2D{
? ? ? ? vector+=vector
? ? ? ? return vector
? ? }
}
var toBeDoubled = Vector2D(x:1.0,y:4.0)
let afterDoubling = +++toBeDoubled
// toBeDoubled now has values of (2.0, 8.0)
// afterDoubling also has values of (2.0, 8.0)
注意與運算符重載的區別
自定義中綴運算符的優先級。一個自定義的中綴運算符如果沒有顯示的放進一個優先級組,那么它會被富裕一個默認的優先級組,高于三元條件運算符的優先級。下面的例子定義了一個新的自定義中綴運算符+-。從屬于運算符組AdditionPrecedence:
infix operator +- : AdditionPrecedence
extension Vector2D{
? ? static func +- ?(left:Vector2D,right:Vector2D) ->Vector2D{
? ? ? ? returnVector2D(x:left.x+right.x,y:left.y-right.y)
? ? }
}
let firstVector = Vector2D(x:1.0,y:2.0)
let secondVector = Vector2D(x:3.0,y:4.0)
let plusMinusVector = firstVector +- secondVector
// plusMinusVector is a Vector2D instance with values of (4.0, -2.0)
AdditionPrecedence的具體細節參考Swift語言參考Operators章節
不需要對前綴或者后綴操作符指定優先級,如果對一個操作數同時應用了前綴以及后綴運算符,后綴運算符首先起作用。