到此為止,除了和指針相關的運算符還沒講之外,其它運算符都講過了,是時候做一個總結了。
運算符+ - * / % > < >= <= == != & | ^ 以及各種復合賦值運算符要求兩邊的操作數類型一致,條件運算符?:要求後兩個操作數類型一致,這些運算符在計算之前都需要做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才能瞭解完整的語法規則。