從最簡單的運算子加號(+)說起,加號(+)是個二元運算子――也就是說,加號只把兩個數聯接起來,從來不把第三個或更多的聯接起來。
因此,「1加2加3」 在計算機中被表述為:
(1 + 2) + 3 // a或者
1 + (2 + 3) // b雖然我們通常寫做1 + 2 + 3,但並不意味著這它和我們數學中的1+2+3 是等價的。
那麼數學中的1+2+3 到底表示的是a 呢,還是b 呢?
如果計算機的求值是左結合的,那麼此表達式等價於第一種a; 如果是右結合的,那麼此表達式等價於第二種b。
1 + 2 + 3 簡單的理解就是“把1、2、3加在一起”, 確實,在我們接觸到的數學裡面,就是把三個數加起來。 但是在程式語言中,卻不只這樣。
就像前面說的那樣,+號無法操作三個或更多的數,參與加法運算的只能是兩個數。
順便說一句,正號、負號是一元運算符,雖然它們和二元運算子加、減用相同的符號, 但是他們卻是不同的,所以不要想當然的認為+4 就等價於0+4 ,其實它們不是等價的,
+4 是整數,但是0+4 是加法表達式,這個表達式的求值結果剛好是+4。
在java 中,我們可以寫short a = +4,但是當我們寫short a = 0 + 4 時則產生一個警告。
還有一個其它例子,同樣是關於short 的,
short b = 1;
short b = b + 4; // 警告
short b += 4; // 無警告那麼1 + 2 + 3 是如何運算的呢? 在馮諾依曼體系架構的程式語言中, 這裡有一個副作用――我習慣稱那些「電腦的運算過程與程式設計師的大腦思考過程不一樣時,則稱為副作用」(雖然書本裡面沒有這麼寫過,但我一向這麼認為), 本來你以為會是這樣,結果計算機偏偏就不是這樣做的,我稱他為副作用。
如果看過前面的『語句與表達式’,這可以這麼理解:
1 + 2 是一個表達式,它的回傳值是3。 這個表達式的回傳值再參加到另一個表達式中3 + 3,最後得到結果6。
我們用語句(Statement)來改寫這段程式碼:
// 計算1 + 2 + 3
var a = 1 + 2;
var b = a + 3;如果我們用lisp 語言對這個表達式求值,則沒有副作用。
(+ (+ 1 2) 3)如果你還沒懂,或這個例子太有特殊性,那我們換一個
5 > 4 > 3在數學中,這個算式的值為true。當我們用C語言來寫這段程式碼,它回傳的確實false。
原因和上面的一樣,大於號(>)是二元運算,它無法直接比較三個數,5 > 4 回傳的結果是true, 當用true 和3 比較時,true 被轉換稱1,也就是1 > 3,最終的結果自然就是false 了。
總之,迴歸到了『語句與表達式』篇的那個觀點:在程式語言中每個表達式都有一個值。
程式語言中的運算子和數學中的運算子雖然一樣,但是它們卻不等同。 當你寫程式時,要寫給人看; 當你調試程式時,要學會用電腦的方式思考程式碼的意思。
我習慣把運算子理解為函數,例如2 + 5 其實就是add(2, 5) 或2.add(5)。 難道我會偷偷的告訴你「其實很多語言都是這麼做的」。