C 語言運算子優先順序

ARM的程式設計師敲著詩歌的夢發表於2018-12-23

C 語言運算子優先順序

優先順序 運算子 描述 結合性
1 ++ -- 字尾自增與自減 從左到右
() 函式呼叫
[] 陣列下標
. 結構體與聯合體成員訪問
-> 結構體與聯合體成員通過指標訪問
(type){list} 複合字面量(C99)
2 ++ -- 字首自增與自減 從右到左
+ - 一元加與減
! ~ 邏輯非、逐位取反
(type) 型別轉換
* 解引用
& 取地址
sizeof 取大小
_Alignof 對其要求(C11)
3 * / % 乘法、除法、求餘 從左到右
4 + - 加法、減法
5 << >> 左移、右移
6 < <= 小於、小於等於
> >= 大於、大於等於
7 == != 等於、不等於
8 & 逐位與
9 ^ 逐位異或
10 | 逐位或
11 && 邏輯與
12 || 邏輯或
13 ? : 三元條件 從右到左
14 = 簡單賦值
+= -= 以和賦值、以差賦值
*= /= %= 以積、商及餘數賦值
<<= >>= 以逐位左移及右移賦值
&= ^= |= 以逐位與、異或及或賦值
15 , 逗號 從左到右

如何理解優先順序

分析表示式時,運算元首先與較高優先順序的運算子結合(如同用括號)。例如,表示式 *p++ ,因為字尾自增++比解引用*的優先順序高,所以p先和++結合,所以被分析為 *(p++),而非 (*p)++

如何理解結合性

當運算子具有相同優先順序時,運算元按照結合性來結合。例如表示式 a = b = c ,b 的兩側都是=,優先順序相同,但是=的結合性是從右到左,即右邊的優先,所以 b 優先與右邊的=結合,所以被分析為 a = (b = c) 而非(a = b) = c

幾點注意

  1. 優先順序或者結合性與求值順序是獨立的。

例如:表示式 f1() + f2() + f3() 被分析成 (f1() + f2()) + f3() ,因為 +的結合性從左到右。但執行時對 f3 的函式呼叫可以最先、最後,或在 f1()f2() 之間求值,同理, f1()f2() 各自的求值順序也不一定。

  1. C 語言標準不指定運算子優先順序。它指定語言文法,而優先順序表格從它匯出,以簡化理解。

  2. 結合性規定對於一元運算子是冗餘的,且只為完備而顯示:一元字首運算子始終從右到左結合(例如++*p++(*p));而一元后綴運算子始終從左到右結合( 例如 a[1][2]++((a[1])[2])++)。

  3. 結合性對成員訪問運算子有意義:a.b++ 分析為(a.b)++而非 a.(b++)

  4. sizeof 的運算元不能是型別轉型:表示式 sizeof (int) * p 無歧義地轉譯成 (sizeof(int)) * p ,而非 sizeof((int)*p)

  5. 條件運算子中部( ?: 之間)的表示式分析為如同加括號:忽略其相對於 ?: 的優先順序。

參考資料

https://zh.cppreference.com/w/c/language/operator_precedence

相關文章