下表列出 C 运算符的优先级和结合性。运算符从顶到底以降序列出。
优先级 | 运算符 | 描述 | 结合性 |
---|---|---|---|
1 | ++ -- |
后缀自增与自减 | 从左到右 |
() |
函数调用 | ||
[] |
数组下标 | ||
. |
结构体与联合体成员访问 | ||
-> |
结构体与联合体成员通过指针访问 | ||
(type){list} |
复合字面量(C99) | ||
2 | ++ -- |
前缀自增与自减 | 从右到左 |
+ - |
一元加与减 | ||
! ~ |
逻辑非与逐位非 | ||
(type) |
类型转型 | ||
* |
间接(解引用) | ||
& |
取址 | ||
sizeof |
取大小 | ||
_Alignof |
对齐要求(C11) | ||
3 | * / % |
乘法、除法及余数 | 从左到右 |
4 | + - |
加法及减法 | |
5 | << >> |
逐位左移及右移 | |
6 | < <= |
分别为 < 与 ≤ 的关系运算符 | |
> >= |
分别为 > 与 ≥ 的关系运算符 | ||
7 | == != |
分别为 = 与 ≠ 关系 | |
8 | & |
逐位与 | |
9 | ^ |
逐位异或(排除或) | |
10 | | |
逐位或(包含或) | |
11 | && |
逻辑与 | |
12 | || |
逻辑或 | |
13[注 2] | ?: |
三元条件 | 从右到左 |
14 | = |
简单赋值 | |
+= -= |
以和及差赋值 | ||
*= /= %= |
以积、商及余数赋值 | ||
<<= >>= |
以逐位左移及右移赋值 | ||
&= ^= |= |
以逐位与、异或及或赋值 | ||
15 | , |
逗号 | 从左到右 |
- ↑
sizeof
的运算数不能是类型转型:表达式sizeof (int) * p
无歧义地转译成(sizeof(int)) * p
,而非sizeof((int)*p)
。 - ↑ 虚构优先级,见下面注意
- ↑ 条件运算符中部(
?
与:
之间)的表达式分析为如同加括号:忽略其相对于?:
的优先级。
分析表达式时,列于上面表中某行的运算符,将比列于低于它的行中拥有较低优先级的任何运算符,更紧密地绑定到其参数(如同用括号)。例如,表达式 *p++ 被分析为 *(p++) ,而非 (*p)++ 。
拥有相同优先级的运算符以其结合性的方向绑定到其参数。例如表达式 a = b = c 被分析为 a = (b = c) 而非 (a = b) = c ,因为从右到左结合性。
注意
优先级和结合性与求值顺序独立。
C 语言标准不指定运算符优先级。它指定语言文法,而优先级表格从它导出,以简化理解。文法有一部分无法以优先级表格表示:不允许赋值表达式作为条件运算符的右侧运算数,故 e = a < d ? a++ : a = d 是不能分析的表达式,从而条件与赋值运算符的相对优先级无法简单描述。
然而,许多 C 编译器使用非标准表达式文法,其中指定 ?:
拥有高于 =
的优先级,这将该表达式分析为 e = ( ((a < d) ? (a++) : a) = d ) ,它因语义制约而编译失败: ?:
决不是左值而 =
要求可修改左值在左侧。此即此页面所呈现的表格。
注意 C++ 中这有别,其中条件运算符与赋值拥有相同优先级。
结合性规定对于一元运算符是冗余的,且只为完备而显示:一元前缀运算符始终从右到左结合( delete ++*p 为 delete(++(*p)) )而一元后缀运算符始终从左到右结合( a[1][2]++ 为 ((a[1])[2])++ )。注意结合性对成员访问运算符有意义,即使在它们与一元后缀运算符组合时: a.b++ 分析为 (a.b)++ 而非 {{c|a.(b++)} 。