下表列出了 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] | = | 简单赋值 | |
+= -= | 按和和差赋值 | ||
*= /= %= | 按乘积、商和余数分配 | ||
<<= >>= | 按位左移和右移赋值 | ||
&= ^= |= | 按位 AND、XOR 和 OR 赋值 | ||
15 | , | 逗号 | 左到右 |
- ↑ 前缀的操作数
++
和--
不能是类型转换。该规则在语法上禁止一些无论如何在语义上无效的表达式。一些编译器忽略此规则并从语义上检测无效。 - ↑ 的操作数
sizeof
不能是类型转换:表达式sizeof (int) * p
被明确解释为(sizeof(int)) * p
,但不是sizeof((int)*p)
。 - ↑ 条件运算符中间的表达式(在
?
and之间:
)被解析为括号:?:
忽略其相对于的优先级。 - ↑ 赋值运算符的左操作数必须是一元(2 级非强制转换)表达式。该规则在语法上禁止一些无论如何在语义上无效的表达式。许多编译器忽略此规则并从语义上检测无效。例如,e = a < d ? 一个++ :一个= d是由于此规则而无法解析的表达式。但是,许多编译器忽略此规则并将其解析为e = ( ( ( a < d ) ? ( a ++ ) : a ) = d ),然后给出一个错误,因为它在语义上是无效的。
解析表达式时,与列在其下方行中的任何运算符相比,在某行上列出的运算符与其参数绑定得更紧密(就像用括号一样)。例如,表达式* p ++ 被解析为 * ( p ++ ),而不是 ( * p ) ++.
同一单元格中的运算符(一个单元格中可能列出多行运算符)在给定方向上以相同的优先级进行计算。例如,表达式a = b = c 被解析为 a = ( b = c ),而不是 ( a = b ) = c 因为从右到左的结合性。
笔记
优先级和关联性与求值顺序无关。
标准本身没有指定优先级。它们来自语法。
在C ++中,条件运算符具有相同的优先级赋值运算符,和前缀++
和--
和赋值运算符没有关于它们的操作数的限制。
结合性规范对于一元运算符来说是多余的,只是为了完整性才显示:一元前缀运算符总是从右到左关联(大小为 ++* p 是 大小(++ (* p ))) 和一元后缀运算符总是从左到右 (一个[ 1 ] [ 2 ] ++ 是 ( ( ( a [ 1 ] ) [ 2 ] ) ++)。请注意,关联性对于成员访问运算符是有意义的,即使它们与一元后缀运算符组合在一起:一种。b ++ 被解析 (一个。b )++ 并不是 一种。( b ++ ).
参考
- 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 表达式