指南:高級(jí)運(yùn)算符(Advanced Operators)

位運(yùn)算符(Bitwise Operators)

  • 位運(yùn)算符可以操作數(shù)據(jù)結(jié)構(gòu)中每個(gè)獨(dú)立的比特位。它們通常被用在底層開發(fā)中烫堤,比如圖形編程和創(chuàng)建設(shè)備驅(qū)動(dòng)荣赶。位運(yùn)算符在處理外部資源的原始數(shù)據(jù)時(shí)也十分有用凤价,比如對(duì)自定義通信協(xié)議傳輸?shù)臄?shù)據(jù)進(jìn)行編碼和解碼。

按位取反運(yùn)算符(Bitwise NOT Operator)

  • 按位取反運(yùn)算符(~)可以對(duì)一個(gè)數(shù)值的全部比特位進(jìn)行取反

  • 按位取反運(yùn)算符是一個(gè)前綴運(yùn)算符讯壶,需要直接放在運(yùn)算的數(shù)之前料仗,并且它們之間不能添加任何空格。

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

按位與運(yùn)算符(Bitwise AND Operator)

  • 按位與運(yùn)算符(&)可以對(duì)兩個(gè)數(shù)的比特位進(jìn)行合并伏蚊。它返回一個(gè)新的數(shù)立轧,只有當(dāng)兩個(gè)數(shù)的對(duì)應(yīng)位都為 1的時(shí)候,新數(shù)的對(duì)應(yīng)位才為 1躏吊。
let firstSixBits: UInt8 = 0b11111100
let lastSixBits: UInt8  = 0b00111111
let middleFourBits = firstSixBits & lastSixBits // 等于 00111100

按位或運(yùn)算符(Bitwise OR Operator)

  • 按位或運(yùn)算符(|)可以對(duì)兩個(gè)數(shù)的比特位進(jìn)行比較氛改。它返回一個(gè)新的數(shù),只要兩個(gè)數(shù)的對(duì)應(yīng)位中有任意一個(gè)為 1時(shí)比伏,新數(shù)的對(duì)應(yīng)位就為 1胜卤。
let someBits: UInt8 = 0b10110010
let moreBits: UInt8 = 0b01011110
let combinedbits = someBits | moreBits // 等于 11111110

按位異或運(yùn)算符(Bitwise XOR Operator)

  • 按位異或運(yùn)算符(^)可以對(duì)兩個(gè)數(shù)的比特位進(jìn)行比較。它返回一個(gè)新的數(shù)赁项,當(dāng)兩個(gè)數(shù)的對(duì)應(yīng)位不相同時(shí)葛躏,新數(shù)的對(duì)應(yīng)位就為 1。
let firstBits: UInt8 = 0b00010100
let otherBits: UInt8 = 0b00000101
let outputBits = firstBits ^ otherBits // 等于 00010001

按位左移悠菜、右移運(yùn)算符(Bitwise Left and Right Shift Operators)

  • 按位左移運(yùn)算符(<<)和按位右移運(yùn)算符(>>)可以對(duì)一個(gè)數(shù)的所有位進(jìn)行指定位數(shù)的左移和右移舰攒。

  • 對(duì)一個(gè)數(shù)進(jìn)行按位左移或按位右移,相當(dāng)于對(duì)這個(gè)數(shù)進(jìn)行乘以 2 或除以 2 的運(yùn)算悔醋。將一個(gè)整數(shù)左移一位摩窃,等價(jià)于將這個(gè)數(shù)乘以 2,同樣地芬骄,將一個(gè)整數(shù)右移一位猾愿,等價(jià)于將這個(gè)數(shù)除以 2。

無符號(hào)整數(shù)的移位運(yùn)算(Shifting Behavior for Unsigned Integers)

  • 已經(jīng)存在的位按指定的位數(shù)進(jìn)行左移和右移账阻。
  • 任何因移動(dòng)而超出整型存儲(chǔ)范圍的位都會(huì)被丟棄蒂秘。
  • 用 0來填充移位后產(chǎn)生的空白位。

這種方法稱為邏輯移位淘太。

let shiftBits: UInt8 = 4 // 即二進(jìn)制的 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

有符號(hào)整數(shù)的移位運(yùn)算(Shifting Behavior for Signed Integers)

  • 當(dāng)對(duì)整數(shù)進(jìn)行按位右移運(yùn)算時(shí),遵循與無符號(hào)整數(shù)相同的規(guī)則嘁捷,但是對(duì)于移位產(chǎn)生的空白位使用符號(hào)位進(jìn)行填充造成,而不是用 0。

  • 由于正數(shù)和負(fù)數(shù)的特殊存儲(chǔ)方式雄嚣,在對(duì)它們進(jìn)行右移的時(shí)候晒屎,會(huì)使它們?cè)絹碓浇咏?0喘蟆。在移位的過程中保持符號(hào)位不變,意味著負(fù)整數(shù)在接近 0的過程中會(huì)一直保持為負(fù)鼓鲁。

溢出運(yùn)算符(Overflow Operators)

可以選擇讓系統(tǒng)在數(shù)值溢出的時(shí)候采取截?cái)嗵幚碓坦欤菆?bào)錯(cuò)『Э裕可以使用 Swift 提供的三個(gè)溢出運(yùn)算符來讓系統(tǒng)支持整數(shù)溢出運(yùn)算橙弱。這些運(yùn)算符都是以 &開頭的

  • 溢出加法 &+
  • 溢出減法 &-
  • 溢出乘法 &*

數(shù)值溢出(Value Overflow)

  • 數(shù)值有可能出現(xiàn)上溢或者下溢。

  • 溢出也會(huì)發(fā)生在有符號(hào)整型數(shù)值上燥狰。在對(duì)有符號(hào)整型數(shù)值進(jìn)行溢出加法或溢出減法運(yùn)算時(shí)棘脐,符號(hào)位也需要參與計(jì)算。

  • 對(duì)于無符號(hào)與有符號(hào)整型數(shù)值來說龙致,當(dāng)出現(xiàn)上溢時(shí)蛀缝,它們會(huì)從數(shù)值所能容納的最大數(shù)變成最小的數(shù)。同樣地目代,當(dāng)發(fā)生下溢時(shí)屈梁,它們會(huì)從所能容納的最小數(shù)變成最大的數(shù)。

var unsignedOverflow = UInt8.max
// unsignedOverflow 等于 UInt8 所能容納的最大整數(shù) 255
unsignedOverflow = unsignedOverflow &+ 1
// 此時(shí) unsignedOverflow 等于 0

var unsignedOverflow1 = UInt8.min
// unsignedOverflow1 等于 UInt8 所能容納的最小整數(shù) 0
unsignedOverflow1 = unsignedOverflow1 &- 1
// 此時(shí) unsignedOverflow1 等于 255

var signedOverflow = Int8.min
// signedOverflow 等于 Int8 所能容納的最小整數(shù) -128
signedOverflow = signedOverflow &- 1
// 此時(shí) signedOverflow 等于 127

優(yōu)先級(jí)和結(jié)合性(Precedence and Associativity)

  • 運(yùn)算符的優(yōu)先級(jí)使得一些運(yùn)算符優(yōu)先于其他運(yùn)算符榛了,高優(yōu)先級(jí)的運(yùn)算符會(huì)先被計(jì)算在讶。

  • 結(jié)合性定義了相同優(yōu)先級(jí)的運(yùn)算符是如何結(jié)合的,也就是說忽冻,是與左邊結(jié)合為一組真朗,還是與右邊結(jié)合為一組。

運(yùn)算符函數(shù)(Operator Functions)

  • 類和結(jié)構(gòu)體可以為現(xiàn)有的運(yùn)算符提供自定義的實(shí)現(xiàn)僧诚,這通常被稱為運(yùn)算符重載遮婶。
struct Vector2D {
    var x = 0.0, y = 0.0
}
func + (left: Vector2D, right: Vector2D) -> Vector2D {
    return Vector2D(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 是一個(gè)新的 Vector2D 實(shí)例,值為 (5.0, 5.0)

前綴和后綴運(yùn)算符(Prefix and Postfix Operators)

  • 類與結(jié)構(gòu)體也能提供標(biāo)準(zhǔn)單目運(yùn)算符的實(shí)現(xiàn)湖笨。

  • 要實(shí)現(xiàn)前綴或者后綴運(yùn)算符旗扑,需要在聲明運(yùn)算符函數(shù)的時(shí)候在 func關(guān)鍵字之前指定 prefix或者 postfix修飾符

prefix func - (vector: Vector2D) -> Vector2D {
    return Vector2D(x: -vector.x, y: -vector.y)
}

let positive = Vector2D(x: 3.0, y: 4.0)
let negative = -positive
// negative 是一個(gè)值為 (-3.0, -4.0) 的 Vector2D 實(shí)例
let alsoPositive = -negative
// alsoPositive 是一個(gè)值為 (3.0, 4.0) 的 Vector2D 實(shí)例

復(fù)合賦值運(yùn)算符(Compound Assignment Operators)

  • 復(fù)合賦值運(yùn)算符將賦值運(yùn)算符(=)與其它運(yùn)算符進(jìn)行結(jié)合。例如慈省,將加法與賦值結(jié)合成加法賦值運(yùn)算符(+=)臀防。

  • 在實(shí)現(xiàn)的時(shí)候,需要把運(yùn)算符的左參數(shù)設(shè)置成 inout類型边败,因?yàn)檫@個(gè)參數(shù)的值會(huì)在運(yùn)算符函數(shù)內(nèi)直接被修改袱衷。

  • 不能對(duì)默認(rèn)的賦值運(yùn)算符(=)進(jìn)行重載。只有組合賦值運(yùn)算符可以被重載笑窜。

  • 無法對(duì)三目條件運(yùn)算符 (a ? b : c) 進(jìn)行重載致燥。

func += (inout left: Vector2D, 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 的值現(xiàn)在為 (4.0, 6.0)

等價(jià)運(yùn)算符(Equivalence Operators)

  • 自定義的類和結(jié)構(gòu)體沒有對(duì)等價(jià)運(yùn)算符進(jìn)行默認(rèn)實(shí)現(xiàn),等價(jià)運(yùn)算符通常被稱為“相等”運(yùn)算符(==)與“不等”運(yùn)算符(!=)排截。對(duì)于自定義類型嫌蚤,Swift 無法判斷其是否“相等”辐益,因?yàn)椤跋嗟取钡暮x取決于這些自定義類型在代碼中所扮演的角色。

  • 為了使用等價(jià)運(yùn)算符能對(duì)自定義的類型進(jìn)行判等運(yùn)算脱吱,需要為其提供自定義實(shí)現(xiàn)智政。

func == (left: Vector2D, right: Vector2D) -> Bool {
    return (left.x == right.x) && (left.y == right.y)
}
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.")
}
// 打印 “These two vectors are equivalent.”

自定義運(yùn)算符(Custom Operators)

  • 除了實(shí)現(xiàn)標(biāo)準(zhǔn)運(yùn)算符,在 Swift 中還可以聲明和實(shí)現(xiàn)自定義運(yùn)算符箱蝠。

  • 新的運(yùn)算符要使用 operator關(guān)鍵字在全局作用域內(nèi)進(jìn)行定義续捂,同時(shí)還要指定 prefix、infix或者 postfix修飾符

prefix operator +++ {}

prefix func +++ (inout vector: Vector2D) -> Vector2D {
    vector += vector
    return vector
}

var toBeDoubled = Vector2D(x: 1.0, y: 4.0)
let afterDoubling = +++toBeDoubled
// toBeDoubled 現(xiàn)在的值為 (2.0, 8.0)
// afterDoubling 現(xiàn)在的值也為 (2.0, 8.0)

自定義中綴運(yùn)算符的優(yōu)先級(jí)和結(jié)合性(Precedence and Associativity for Custom Infix Operators)

  • 自定義的中綴運(yùn)算符也可以指定優(yōu)先級(jí)和結(jié)合性抡锈。

  • 結(jié)合性可取的值有l(wèi)eft疾忍,right和 none。

  • 結(jié)合性的默認(rèn)值是 none床三,優(yōu)先級(jí)的默認(rèn)值 100一罩。

  • 當(dāng)定義前綴與后綴運(yùn)算符的時(shí)候,我們并沒有指定優(yōu)先級(jí)撇簿。然而聂渊,如果對(duì)同一個(gè)值同時(shí)使用前綴與后綴運(yùn)算符,則后綴運(yùn)算符會(huì)先參與運(yùn)算四瘫。

infix operator +- { associativity left precedence 140 }
func +- (left: Vector2D, right: Vector2D) -> Vector2D {
    return Vector2D(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 是一個(gè) Vector2D 實(shí)例汉嗽,并且它的值為 (4.0, -2.0)

  • 賦值運(yùn)算符=不能重載,其實(shí)就是復(fù)制找蜜”睿可以通過協(xié)議的方式實(shí)現(xiàn),比如考慮遵循NSCopying協(xié)議
  • 運(yùn)算符重載函數(shù)都是全局函數(shù)洗做,不要拘泥于“面向?qū)ο蟮脑O(shè)計(jì)方法”了弓叛。這些函數(shù)放在類或者結(jié)構(gòu)體、枚舉同一個(gè)源文件中诚纸,但是寫在{}之外撰筷。
  • 從理解的角度講,運(yùn)算符重載還是用全局函數(shù)的方式比較好畦徘。
  • Swift兼容Object-C部分是面向?qū)ο蟊献眩袆?dòng)態(tài)特性的。但是Swift本身是靜態(tài)的井辆,類型安全的关筒,沒有動(dòng)態(tài)特性。另外杯缺,也不全是面向?qū)ο蟮钠轿窠Y(jié)構(gòu)體,枚舉夺谁,常用的集合等等廉赔,跟面向?qū)ο蠖紱]什么關(guān)系。編程的思路需要進(jìn)一步拓展匾鸥。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蜡塌,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子勿负,更是在濱河造成了極大的恐慌馏艾,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奴愉,死亡現(xiàn)場(chǎng)離奇詭異琅摩,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)锭硼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門房资,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人檀头,你說我怎么就攤上這事轰异。” “怎么了暑始?”我有些...
    開封第一講書人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵搭独,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我廊镜,道長(zhǎng)牙肝,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任嗤朴,我火速辦了婚禮配椭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘播赁。我一直安慰自己颂郎,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開白布容为。 她就那樣靜靜地躺著乓序,像睡著了一般。 火紅的嫁衣襯著肌膚如雪坎背。 梳的紋絲不亂的頭發(fā)上替劈,一...
    開封第一講書人閱讀 49,111評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音得滤,去河邊找鬼陨献。 笑死,一個(gè)胖子當(dāng)著我的面吹牛懂更,可吹牛的內(nèi)容都是我干的眨业。 我是一名探鬼主播急膀,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼龄捡!你這毒婦竟也來了卓嫂?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤聘殖,失蹤者是張志新(化名)和其女友劉穎晨雳,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體奸腺,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡餐禁,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了突照。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片帮非。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖绷旗,靈堂內(nèi)的尸體忽然破棺而出喜鼓,到底是詐尸還是另有隱情,我是刑警寧澤衔肢,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布庄岖,位于F島的核電站,受9級(jí)特大地震影響角骤,放射性物質(zhì)發(fā)生泄漏隅忿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一邦尊、第九天 我趴在偏房一處隱蔽的房頂上張望背桐。 院中可真熱鬧,春花似錦蝉揍、人聲如沸链峭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)弊仪。三九已至,卻和暖如春杖刷,著一層夾襖步出監(jiān)牢的瞬間励饵,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工滑燃, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留役听,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像典予,于是被迫代替她去往敵國(guó)和親甜滨。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容