C Operator Precedence
以下表格按优先级从高到低列出了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 |
,
|
逗号运算符 | 从左到右 |
-
↑
前缀
++和--的操作数不能是类型转换。该规则在语法层面禁止了某些语义上本就无效的表达式。部分编译器会忽略此规则并通过语义分析检测无效性。 -
↑
sizeof的操作数不能是类型转换:表达式 sizeof ( int ) * p 明确解释为 ( sizeof ( int ) ) * p ,而非 sizeof ( ( int ) * p ) 。 -
↑
条件运算符中间表达式(位于
?和:之间)的解析方式如同被括号包围:其与?:的优先级关系会被忽略。 - ↑ 赋值运算符的左操作数必须是一元(二级非转换)表达式。该规则在语法层面禁止了某些语义上本就无效的表达式。许多编译器会忽略此规则并通过语义分析检测无效性。例如, 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 ++* p 即 sizeof ( ++ ( * p ) ) ),而单目后缀运算符始终从左向右结合( a [ 1 ] [ 2 ] ++ 即 ( ( a [ 1 ] ) [ 2 ] ) ++ )。需注意结合性对成员访问运算符同样具有意义,尽管它们被归为单目后缀运算符: a. b ++ 会被解析为 ( a. b ) ++ 而非 a. ( b ++ ) 。
参考文献
- C17 标准 (ISO/IEC 9899:2018):
-
- A.2.1 表达式
- C11 标准 (ISO/IEC 9899:2011):
-
- A.2.1 表达式
- C99标准(ISO/IEC 9899:1999):
-
- A.2.1 表达式
- C89/C90 标准 (ISO/IEC 9899:1990):
-
- A.1.2.1 表达式
参见
求值顺序 在运行时对运算符操作数的执行顺序。
| 常用运算符 | ||||||
|---|---|---|---|---|---|---|
| 赋值 |
自增
自减 |
算术 | 逻辑 | 比较 |
成员
访问 |
其他 |
|
a
=
b
|
++
a
|
+
a
|
!
a
|
a
==
b
|
a
[
b
]
|
a
(
...
)
|
|
C++ 文档
关于
C++ operator precedence
|