c 語言優先順序

2021-06-19 15:44:26 字數 2919 閱讀 4351

link:

... blog&id=2880933

寫**的時候,常會翻看的乙個表就是「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

順口溜 

C語言優先順序

優先順序 運算子名稱或含義 使用形式 結合方向說明1 陣列下標 陣列名 常量表示式 左到右 圓括號 表示式 函式名 形參表 成員選擇 物件 物件.成員名 成員選擇 指標 物件指標 成員名2 負號運算子 表示式 右到左單目運算子 型別 強制型別轉換 資料型別 表示式 自增運算子 變數名 變數名 單目運...

C語言優先順序

優先順序 運算子名稱或含義 使用形式 結合方向說明1 陣列下標 陣列名 常量表示式 左到右 圓括號 表示式 函式名 形參表 成員選擇 物件 物件.成員名 成員選擇 指標 物件指標 成員名2 負號運算子 表示式 右到左單目運算子 型別 強制型別轉換 資料型別 表示式 自增運算子 變數名 變數名 單目運...

C語言優先順序

優先順序 運算子名稱或含義 使用形式 結合方向 說明陣列下標 陣列名 常量表示式 左到右圓括號 表示式 函式名 形參表 成員選擇 物件 物件.成員名 成員選擇 指標 物件指標 成員名 負號運算子 常量右到左 單目運算子 type 強制型別轉換 資料型別 表示式 自增運算子 變數名 單目運算子 自減運...