細說C語言的優先級和結合性


Table
0. 為什么要掌握優先級
1. 優先級
1.1 優先級圖表
1.2 運算符實例
1.3 優先級順口溜
2. 結合性
3. 參考資料

寫代碼的時候,常會翻看的一個表就是“c語言運算符優先級表”。c的運算符優先級常常很讓人頭疼。其實,在大學里學習c的時候,老師告訴大家這個不用一定背下來,用的時候可以找書,或者加小括號就可以了。我聽了,但是后來發現錯了。很多人都聽了,但不是每個人都發現這是錯的。以至於有人覺得把優先級背下來是“沒事閑的”


0. 為什么要掌握優先級

想想這兩個問題:
a. 讀別人的代碼,遇到優先級問題看不懂,怎么辦?
b. 一堆的括號,美觀嗎?
本想貼一張畫來裝飾牆壁,卻用了一堆紙來固定!
有人說代碼寫多了,自然就會了。這個是很寬泛的說法。看你寫的代碼的水准,有些東西可能你一直都接觸不到,何談熟練。有些東西一定要梳理,總結。

1. 優先級

1.1 優先級圖表

  • 優先級最高者不是真正意義上的運算符,包括:數組下標,函數調用,結構體成員選擇符。
  • 單目運算符的優先級次之。(! ~ ++ -- - (type) * & sizeof)
  • 然后是雙目運算符。雙目運算符里, 算數運算符(* / % + -)優先級最高, 移位(<< >>)次之, 關系運算符(< <= > >= != ==)再次之, 接着是位運算符(& ^ | ),邏輯運算符(&& ||) 條件運算符(?: 三目),賦值運算符(= ...)。
  • 任何一個邏輯運算符的優先級低於任何一個關系運算符。
  • 移位運算符的優先級比算數運算符要低,但是比關系運算符要高。


1.2 運算符實例
a. while (c = getc(in) != EOF)
putc(c, out)
循環的意思是復制一個文件到另一個文件。但是由於!=的優先級比賦值運算符的優先級高,所以c被賦予了getc()的返回值與EOF比較后的布爾值,結果向out中寫入了一堆1.
b. 解釋下面幾個聲明
char *p[];
char (*p)[];
int *fp();
int (*fp)();

char *p[]
常常被錯誤的理解為指向字符數組的指針。
正確的是p一個數組,里面元素是指向字符的指針類型。
char (*p)[]
p是指向指向字符數組的指針。
int *fp()
常常錯誤理解為函數指針,該函數返回int類型。
正確的是fp是一個函數,他返回一個執行int的指針。
int (*fp)()
fp是函數指針,該函數返回int類型。

c. 解釋下面的表達式
*p.f;
val & mask != 0;
max = val1 > val2 ? val1 : val2;

*p.f
對p去f偏移,作為指針,然后進行解引用。相當與*(p.f),因為.的優先級高與*。比較(*p).f。
val & mask != 0
相當與val & (mask != 0).
max = val1 > val2 ? val1 : val2
相當與 max = (val1 > val2 ? val1 :val2).

d. 一個復雜的聲明

char *(* c[10])(int **p);
1. 有兩個小括號,小括號的結合行是自左向右,所以我們先關注第一個小括號,簡化聲明(*c[10])();
c是一個數組,里面放10指針,后面緊跟這一個括號,所以這些指針是函數指針。
2. 關注第二個括號,(int **p)
顯然p是函數的參數,它是個指向指針的指針。
3. 這看最前面的*
char *說明該函數的返回值是一個指向字符的指針。
4. 這個聲明的意思就是:c是一個數組,里面有10個函數指針,指向的函數返回指針,指向字符,函數的參數是指向int類型指針的指針。

1.3 優先級順口溜
醋壇酸味灌
味落跳福豆

共44個運算符

醋-初等,4個: ( ) [ ] -> 指向結構體成員 . 結構體成員
壇-單目,9個: ! ~ ++ -- -負號 (類型) *指針 &取地址 sizeof長度
酸-算術,5個: * / % + -減
味-位移,2個: << >>
灌-關系,6個: < <= > >= == 等於 != 不等於
味-位邏,3個: & 按位與 ^ 按位異或 | 按位或
落-邏輯,2個: && 邏輯與 || 邏輯或
跳-條件,1個,三目: ? :
福-賦值,11個: = += -= *= /= %= >>= <<= &= ^= |=
豆-逗號,1個: ,

我更推薦在原理上理解以及長時間的使用來掌握,這順口溜是網上剛剛翻到的,覺得挺好,輔助記憶。

2. 結合性
在標准C語言的文檔里,對操作符的結合性並沒有作出非常清楚的解釋。一個滿分的回答是:它是仲裁者,在幾個操作符具有相同的優先級時決定先執行哪一個。
看例子:
int a, b = 1, c = 2;
a = b = c;
這個表達式只有賦值符,這樣優先級就無法幫助我們呢決定哪個操作先執行。如果a = b先執行,然后 b = c執行。那么a最終取1。如果b = c先執行, a = b后執行,那么a最終取2。到底哪一個先執行?看結合性,復制的結合性是右至左,所以b = c,然后a = b。
同級的操作符,結合性相同。如果在計算表達式的值時候需要考慮結合性,那么最好把這個表達式一分為二。

3. 參考資料
《c Traps and Pitfalls》 Andrew Koenig著, ISBN 978-7-115-17179-5
《c 專家編程》 Peter Van Der Linden 著, ISBN 978-7-115-17180-1

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM