C 运算符优先级

来自cppreference.com
< c‎ | language

下表列出 C 运算符的优先级和结合性。运算符从顶到底以降序列出。

优先级 运算符 描述 结合性
1 ++ -- 前缀自增与自减 从左到右
() 函数调用
[] 数组下标
. 结构体与联合体成员访问
-> 结构体与联合体成员通过指针访问
(type){list} 复合字面量(C99)
2 ++ -- 后缀自增与自减 从右到左
+ - 一元加与减
! ~ 逻辑非与逐位非
(type) 类型转型
* 间接(解引用)
& 取址
sizeof 取大小[注 1]
_Alignof 对齐要求(C11)
3 * / % 乘法、除法及余数 从左到右
4 + - 加法及减法
5 << >> 逐位左移及右移
6 < <= 分别为 < 与 ≤ 的关系运算符
> >= 分别为 > 与 ≥ 的关系运算符
7 == != 分别为 = 与 ≠ 关系
8 & 逐位与
9 ^ 逐位异或(排除或)
10 | 逐位或(包含或)
11 && 逻辑与
12 || 逻辑或
13[注 2] ?: 三元条件[注 3] 从右到左
14 = 简单赋值
+= -= 以和及差赋值
*= /= %= 以积、商及余数赋值
<<= >>= 以逐位左移及右移赋值
&= ^= |= 以逐位与、异或及或赋值
15 , 逗号 从左到右
  1. sizeof 的运算数不能是类型转型:表达式 sizeof (int) * p 无歧义地转译成 (sizeof(int)) * p ,而非 sizeof((int)*p)
  2. 虚构优先级,见下面注意
  3. 条件运算符中部( ?: 之间)的表达式分析为如同加括号:忽略其相对于 ?: 的优先级。

分析表达式时,列于上面表中某行的运算符,将比列于低于它的行中拥有较低优先级的任何运算符,更紧密地绑定到其参数(如同用括号)。例如,表达式 *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 ++*pdelete(++(*p)) )而一元后缀运算符始终从左到右结合( a[1][2]++((a[1])[2])++ )。注意结合性对成员访问运算符有意义,即使在它们与一元后缀运算符组合时: a.b++ 分析为 (a.b)++ 而非 {{c|a.(b++)} 。

[编辑] 引用

  • C11 standard (ISO/IEC 9899:2011):
  • A.2.1 Expressions
  • C99 standard (ISO/IEC 9899:1999):
  • A.2.1 Expressions
  • C89/C90 standard (ISO/IEC 9899:1990):
  • A.1.2.1 Expressions

[编辑] 参阅

运行时运算符参数的求值顺序

常用运算符
赋值 自增
自减
算术 逻辑 比较 成员
访问
其他

a = b
a += b
a -= b
a *= b
a /= b
a %= b
a &= b
a |= b
a ^= b
a <<= b
a >>= b

++a
--a
a++
a--

+a
-a
a + b
a - b
a * b
a / b
a % b
~a
a & b
a | b
a ^ b
a << b
a >> b

!a
a && b
a || b

a == b
a != b
a < b
a > b
a <= b
a >= b

a[b]
*a
&a
a->b
a.b

a(...)
a, b
(type) a
? :
sizeof
_Alignof
(C11 起)

C++ 运算符优先级C++ 文档