C 运算符优先级

来自cppreference.com
< c‎ | language


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

优先级运算符描述结合性
1++ --后缀自增与自减从左到右
()函数调用
[]数组下标
.结构体与联合体成员访问
->结构体与联合体成员通过指针访问
(type){list}复合字面量(C99)
2++ --前缀自增与自减[注 1]从右到左
+ -一元加与减
! ~逻辑非与按位取反
(type)转换
*间接(解引用)
&取址
sizeof取大小[注 2]
_Alignof对齐要求(C11)
3* / %乘法、除法及余数从左到右
4+ -加法及减法
5<< >>按位左移及右移
6< <=分别为 < 与 ≤ 的关系运算符
> >=分别为 > 与 ≥ 的关系运算符
7== !=分别为 = 与 ≠ 关系
8&按位与
9^按位异或(排除或)
10|按位或(包含或)
11&&逻辑与
12||逻辑或
13?:三元条件[注 3]从右到左
14[注 4]=简单赋值
+= -=加法和减法赋值
*= /= %=乘法、除法和取余赋值
<<= >>=按位左移和右移赋值
&= ^= |=按位与、异或和或赋值
15,逗号从左到右
  1. 前缀 ++-- 的运算数不能是转换。此规则在文法上禁止某些表达式本来也会在语义上非法的表达式。某些编译器忽略此规则并检测语义上的非法。
  2. sizeof 的运算数不能是转换:表达式 sizeof (int) * p 无歧义地转译成 (sizeof(int)) * p ,而非 sizeof((int)*p)
  3. 条件运算符中部(?: 之间)的表达式分析为如同加括号:忽略其相对于 ?: 的优先级。
  4. 赋值运算符的左运算数必须是一元(第 2 级非转换)表达式。此规则在文法上禁止某些表达式本来也会在语义上非法的表达式。从而许多编译器忽略此规则并在语义上检测其非法。例如, e = a < d ? a++ : a = d 是因此规则而无法剖析的表达式。然而许多编译器忽略此规则并将它剖析成 e = ( ((a < d) ? (a++) : a) = d ),并给出错误,因为它在语义上非法。

分析表达式时,列于上面表中某行的运算符,将比列于低于它的行中拥有较低优先级的任何运算符,更紧密地绑定到其参数(如同用括号)。例如,表达式 *p++ 被分析为 *(p++),而非 (*p)++

拥有相同优先级的运算符以其结合性的方向绑定到其参数。例如表达式 a=b=c 被分析为 a=(b=c) 而非 (a=b)=c,因为从右到左结合性。

注解

优先级和结合性与求值顺序相互独立。

标准自身并未指定优先级。它们是从文法中导出的。

C++ 中,条件运算符拥有与赋值运算符相同的优先级,而前缀 ++-- 及赋值运算符无关于其运算数的限制。

结合性规定对于一元运算符是冗余的,且只为完备而显示:一元前缀运算符始终从右到左结合(sizeof ++*psizeof(++(*p)))而一元后缀运算符始终从左到右结合(a[1][2]++((a[1])[2])++)。注意结合性对成员访问运算符有意义,即使在它们与一元后缀运算符组合时:a.b++ 分析为 (a.b)++ 而非 a.(b++)

引用

  • C17 标准(ISO/IEC 9899:2018):
  • A.2.1 Expressions
  • C11 标准(ISO/IEC 9899:2011):
  • A.2.1 Expressions
  • C99 标准(ISO/IEC 9899:1999):
  • A.2.1 Expressions
  • C89/C90 标准(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
a ? b : c
sizeof


_Alignof
(C11 起)(C23 前)

alignof
(C23 起)

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