第 10 講:運(yùn)算符(二):自增自減運(yùn)算符
之前我們說到了基本的算術(shù)運(yùn)算符,今天我們來說一下自增自減運(yùn)算符。自增自減運(yùn)算符是專門針對(duì)于一個(gè)變量本身進(jìn)行增大和減小操作的運(yùn)算符。
Part 1 前綴和后綴運(yùn)算
在這之前,我們先說一個(gè)概念。前綴運(yùn)算符(Prefix Operator)是指,運(yùn)算符放在變量的左邊的行為;后綴運(yùn)算符(Suffix Operator)則相反:放在變量的右側(cè)的行為。
C# 里的自增運(yùn)算符寫成 ++
、自減運(yùn)算符寫成 --
。這兩個(gè)運(yùn)算符既可充當(dāng)前綴運(yùn)算符,也可以充當(dāng)后綴運(yùn)算符。用法是這樣的:
比如這個(gè)例子里,a++
里的 ++
放在變量后,所以稱為后綴運(yùn)算符;++a
的 ++
和之前的算術(shù)運(yùn)算符不同,算術(shù)運(yùn)算符并不能像這樣單獨(dú)使用,而必須依賴于賦值行為。因?yàn)樗阈g(shù)運(yùn)算符將兩個(gè)數(shù)值關(guān)聯(lián)起來,進(jìn)行運(yùn)算;然后得到的結(jié)果還必須得賦值給另外一個(gè)變量,否則這個(gè)數(shù)值結(jié)果就“找不到”了;而自增自減運(yùn)算符并不一樣,它可以單獨(dú)使用。下面我們來挨個(gè)進(jìn)行說明。
Part 2 前綴自增自減運(yùn)算
前綴自增運(yùn)算和前綴自減運(yùn)算的行為類似,因此放在一起說明。
首先,a
是沒有賦值的狀態(tài),而 b
初始數(shù)值是 4。第二句話,a = ++b
表示,將 ++b
的結(jié)果賦值給 a
。
下面說一下 ++
和 --
++
:將緊挨著的這個(gè)變量先自增一個(gè)單位大小,一般用于整數(shù)數(shù)值(小數(shù)也可以自增一個(gè)單位,不過一般用不上);--
:將緊挨著的這個(gè)變量先自減一個(gè)單位大?。ㄍ希?shù)也可以用,但一般用于整數(shù))。
如果把 ++
作為前綴運(yùn)算,那么自增運(yùn)算過程必須先執(zhí)行;當(dāng)自增完成后,自增完畢后的結(jié)果會(huì)提供給語句的別處使用;--
是同理的,只是把自增操作改成自減操作。
這句話意思就是,a = ++b
里會(huì)用到 b
的結(jié)果的地方除了 ++
(自增)以外,還有 =
(賦值)。按照邏輯,由于是前綴運(yùn)算,因此變量 b
會(huì)因?yàn)閮?yōu)先執(zhí)行自增運(yùn)算的關(guān)系,將原始的數(shù)值 4 變?yōu)?5。接著,++b
整體的結(jié)果也是這個(gè) 5,于是將 5 賦值給變量 a
。整體就是這個(gè)邏輯。所以,前綴自增運(yùn)算符包含兩個(gè)語義:
將變量本身自增一個(gè)單位;
表達(dá)式整體也和算術(shù)運(yùn)算符一樣,有一個(gè)結(jié)果。這個(gè)結(jié)果就是變量增大后的結(jié)果。
同理,--
一樣的。
b
會(huì)變?yōu)?3,然后得到 --b
整體的結(jié)果也是 3。最后把 3 賦值給 a
,完成操作。
Part 3 后綴自增自減運(yùn)算
麻煩的事情來了。前綴運(yùn)算看起來運(yùn)算很簡(jiǎn)單,不過后綴運(yùn)算就麻煩了。++
和 --
是可以作為后綴運(yùn)算出現(xiàn)的,因此更不好理解的是這里。
++
:優(yōu)先將變量本身的數(shù)值丟給別處使用;當(dāng)當(dāng)前語句的別處全部用完這個(gè)變量的數(shù)值后,變量再增大一個(gè)單位;--
:同理,只是改成減去一個(gè)單位。
我們看一下這個(gè)例子。
這個(gè)例子里,a = b++
里使用 b
的地方有兩處:=
(賦值)和 ++
(自增)。由于是后綴運(yùn)算,因此變量 b
b
變量”的地方了。顯然,除了自增以外,只有賦值在用 b
。因此,a = b++
等效于直接先賦值:a = b
,然后 b
增大一個(gè)單位。因此,a
在獲取數(shù)值的時(shí)候,還是 b
原本的數(shù)值 4,而不是 5;但 a = b++
執(zhí)行完畢后,b
會(huì)自增一個(gè)單位,從 4 變?yōu)?5。
道理也不難。將 a = b++
改成 a = b--
是一樣的道理,只是把自增改成自減。因此 a
結(jié)果依舊是 4,只是 b
從原本的數(shù)值 4 變成 3。
Part 4 將自增自減運(yùn)算單獨(dú)作為語句使用
前文里我們還說到了一種用法:a++;
,即單獨(dú)把自增自減運(yùn)算符當(dāng)成語句來用。這樣的操作和前文的前綴和后綴操作是一樣的,只是特殊之處在于,“別處使用變量”的行為就沒有了:整個(gè)語句唯一的操作就是在自增(或自減)變量數(shù)值。
如果單獨(dú)作為語句使用,++a
和 a++
完全沒有區(qū)別(行為上就是單純?yōu)榱俗兞勘旧砟茉龃蠡驕p小一個(gè)單位)。同理,--a
和 a--
也是一樣。
可能你學(xué)過一些匯編語言,C 語言里
++a
和a++
作為語句的時(shí)候,在匯編執(zhí)行上有一點(diǎn)點(diǎn)不同(所以有些人會(huì)告訴你優(yōu)化性能的時(shí)候,請(qǐng)優(yōu)先使用前綴的自增自減運(yùn)算,而不是后綴的;但是實(shí)際上,通過編譯器優(yōu)化,它們都會(huì)變成完全一樣的東西。這一點(diǎn)在 C# 里,不論是前綴還是后綴,都是完全一樣的:只要++a
和a++
作為語句單獨(dú)出現(xiàn)的話,不論在哪里,它們都是一樣的東西。請(qǐng)務(wù)必記住這一點(diǎn)。雖然考試不考,但是一定不要在這種地方上鉆牛角尖。
另外,a++;
完全等價(jià)于這么一句話:a = a + 1;
。這句話未免有些奇怪,在初學(xué) C 語言的時(shí)候,我們就對(duì)這個(gè)左右完全不相等的表達(dá)式頭疼。實(shí)際上,這個(gè)等號(hào)是賦值行為,因此實(shí)際上就是把 a
的數(shù)值增大一個(gè)單位之后,得到的 a + 1
的結(jié)果,再重新賦值給 a
自身的過程;同理,a--;
等價(jià)于 a = a - 1;
。
Part 5 混用自增自減運(yùn)算
5-1 復(fù)雜用例
有些時(shí)候,為了簡(jiǎn)化代碼的書寫,我們可能會(huì)使用自增自減運(yùn)算符。但是,有可能多個(gè)自增自減運(yùn)算符會(huì)同時(shí)出現(xiàn)在一個(gè)語句里。
思考一下,這個(gè)例子的輸出結(jié)果是多少。答案是 8,因?yàn)橛幸粋€(gè)自增運(yùn)算符是作后綴的,所以變量會(huì)先提供別處使用。整個(gè)表達(dá)式里,使用 a
+
和 ++
兩處。那么“別處”自然就指的是這里的 +
了。即使我們打了括號(hào),但是因?yàn)槌霈F(xiàn)在變量的后面,所以 ++
也不會(huì)提前執(zhí)行。這一點(diǎn)在初學(xué)是非常讓人頭疼的。
接著,a
既然提供使用,那么原始數(shù)值是 3。
然后,++b
的 ++
是前綴運(yùn)算,因此會(huì)先將 b
增大一個(gè)單位后,再提供給別處使用。b
從 4 改成 5。b
自增完成后,提供給別處使用(這里還是只有 +
在用 b
)。綜合前面的 a
,我們可以發(fā)現(xiàn),實(shí)際上 c
賦值的時(shí)候,a + b
的結(jié)果其實(shí)是 3 + 5
而不是別的,因此 c
的結(jié)果是 8。
不過,當(dāng)我們走到第 3 行代碼的時(shí)候,a
和 b
變量已經(jīng)通過原始的自增操作完成了增大一個(gè)單位的過程,因此 a
是 4、b
是 5,c
是 8,也因此,輸出結(jié)果是 4, 5, 8
。
混用自增自減運(yùn)算有時(shí)候是可以簡(jiǎn)化代碼,但有時(shí)候會(huì)復(fù)雜化代碼的理解邏輯,因此,謹(jǐn)慎使用類似前面這個(gè)例子這樣的混用模式。
5-2 千萬別混用同一個(gè)變量的自增自減
像是前面這個(gè)例子邏輯還算清晰。如果這樣呢:
我估計(jì)專業(yè)學(xué)過 C# 的朋友也沒幾個(gè)看得懂這個(gè)例子的計(jì)算,以及結(jié)果輸出。想聽我告訴你答案嗎?
從人類的理解角度來說,我們肯定會(huì)優(yōu)先計(jì)算 ++a
。但自增后的 a
會(huì)不會(huì)影響到左邊的 a++
的 a
呢?按道理是會(huì)的,畢竟是同一個(gè) a
;然后得到 b
的結(jié)果 4 + 4(前面這個(gè)是后綴運(yùn)算,因此先用于加法運(yùn)算,之后才自增)。所以答案是 a = 5、b = 8。
但是!你真的覺得這個(gè)是人應(yīng)該寫出來的程序嗎?這種反人類的例子還是不要出現(xiàn)在你的代碼里。
VS 的結(jié)果就是 5 和 8。
呃……我剛還說不告訴你結(jié)果,結(jié)果這里還推了一遍結(jié)果,還講了一遍……
Part 6 總結(jié)
這一節(jié)的內(nèi)容我們學(xué)到了自增和自減運(yùn)算。自增自減運(yùn)算都有如下兩個(gè)語義行為:
把變量的增大(或減小)一個(gè)單位大??;
將變量的結(jié)果當(dāng)作自增自減運(yùn)算符這個(gè)表達(dá)式的數(shù)值,提供給當(dāng)前語句的別處使用。
但我們說過,混用會(huì)引起代碼邏輯的混亂,因此不建議混用自增自減運(yùn)算。最不建議的就是同變量的自增自減。