4. 運算符總結

到此為止,除了和指針相關的運算符還沒講之外,其它運算符都講過了,是時候做一個總結了。

運算符+ - * / % > < >= <= == != & | ^ 以及各種復合賦值運算符要求兩邊的操作數類型一致,條件運算符?:要求後兩個操作數類型一致,這些運算符在計算之前都需要做Usual Arithmetic Conversion。

下面按優先順序從高到低的順序總結一下C語言的運算符,每一條所列的各運算符具有相同的優先順序,對於同一優先順序的多個運算符按什麼順序計算也有說明,雙目運算符就簡單地用“左結合”或“右結合”來說明了。和指針有關的運算符* & ->也在這裡列出來了,到第 23 章 指針再詳細解釋。

1、標識符、常量、字元串和用()括號套起來的表達式是組成表達式的最基本單元,在運算中做操作數,優先順序最高。

2、尾碼運算符,包括數組取下標[]、函數調用()、結構體取成員“.”、指向結構體的指針取成員->、尾碼自增++、尾碼自減--。如果一個操作數後面有多個尾碼,按照離操作數從近到遠的順序(也就是從左到右)依次計算,比如a.name++,先算a.name,再++,這裡的.name應該看成a的一個尾碼,而不是把.看成雙目運算符。

3、單目運算符,包括首碼自增++、首碼自減--、sizeof、類型轉換()、取地址運算&、指針間接定址*、正號+、負號-、按位取反~、邏輯非!。如果一個操作數前面有多個首碼,按照離操作數從近到遠的順序(也就是從右到左)依次計算,比如!~a,先算~a,再求!。

4、乘*、除/、模%運算符。這三個運算符是左結合的。

5、加+、減-運算符。左結合。

6、移位運算符<<和>>。左結合。

7、關係運算符< > <= >=。左結合。

8、相等性運算符==和!=。左結合。

9、按位與&。左結合。

10、按位異或^。左結合。

11、按位或|。左結合。

12、邏輯與&&。左結合。

13、邏輯或||。左結合。

14、條件運算符:?。在第 2 節 “if/else語句”講過Dangling-else問題,條件運算符也有類似的問題。例如a ? b : c ? d : e是看成(a ? b : c) ? d : e還是a ? b : (c ? d : e)呢?C語言規定是後者。

15、賦值=和各種復合賦值(*= /= %= += -= <<= >>= &= ^= |=)。在雙目運算符中只有賦值和復合賦值是右結合的。

16、逗號運算符。左結合。

[K&R]第2章也有這樣一個列表,但是對於結合性解釋得不夠清楚。左結合和右結合這兩個概念只對雙目運算符有意義,對於首碼、尾碼和三目運算符我單獨做了說明。C語言表達式的詳細語法規則可以參考[C99]的Annex A.2,其實語法規則並不是用優先順序和結合性這兩個概念來表述的,有一些細節用優先順序和結合性是表達不了的,只有看C99才能瞭解完整的語法規則。

習題

1、以下代碼得到的sum是0xffff,對嗎?

int i = 0;
unsigned int sum = 0;
for (; i < 16; i++)
	sum = sum + 1U<<i;