一个表达式可以包含多个运算符。在这种情况下,运算符的优先级决定表达式的哪部分被处理为每个运算符的操作数。 例如,按照运算规则,表达式中 *、/、以及 % 的优先级比 + 和 - 高。如下列表达式:
a - b * c
相当于 a - (b * c)
如果想让操作数以不同的方式组合在一起,则必须使用括号,如:
(a - b) * c
此时先计算a-b的值再与c相乘
如果一个表达式中的两个操作数具有相同的优先级,那么它们的结合律(associativity)决定它们的组合方式是从左到右或是从右到左。 例如,算术运算符和操作数的组合方式是从左到右,赋值运算符则是从右到左,如表 1 所示。
表一
表达式 | 结合率 | 公式 |
---|---|---|
a/b%c | 从左到右 | (a/b)%c |
a=b=c | 从右到左 | a=(b=c ) |
表 2 列出优先级次序下,所有 C 语言运算符的优先级和结合律。
表二
优先级 | 运算符 | 描述 | 结合律 |
1 | [] | 数组下标 | 从左到右 |
() | 圆括号 | ||
. | 成员选择(对象) | ||
-> | 成员选择(指针) | ||
++ | 后缀自加运算 | ||
-- | 后缀自减运算 | ||
2 | (类型) | 强制类型转换 | 从右到左 |
- | 负号运算符 | ||
++ | 前置自加运算 | ||
-- | 前置自减运算 | ||
! | 逻辑非运算符 | ||
~ | 按位取反运算符 | ||
* | 取值运算符 | ||
& | 取地址运算符 | ||
sizeof | 长度运算符 | ||
3 | * | 乘 | 从左到右 |
/ | 除 | ||
% | 余数(取模) | ||
4 | + | 加 | 从左到右 |
- | 减 | ||
5 | >> | 右移 | 从左到右 |
<< | 左移 | ||
6 | > | 大于 | 从左到右 |
>= | 大于等于 | ||
< | 小于 | ||
<= | 小于等于 | ||
7 | == | 等于 | 从左到右 |
!= | 不等于 | ||
8 | & | 按位与 | 从左到右 |
9 | ^ | 按位异或 | 从左到右 |
10 | | | 按位或 | 从左到右 |
11 | && | 逻辑与 | 从左到右 |
12 | || | 逻辑或 | 从左到右 |
13 | ?: | 条件运算符 | 从右到左 |
14 | = | 赋值运算符 | 从右到左 |
/= | 除后赋值 | ||
*= | 乘后赋值 | ||
%= | 取模后赋值 | ||
+= | 加后赋值 | ||
-= | 减后赋值 | ||
<<= | 左移后赋值 | ||
>>= | 右移后赋值 | ||
&= | 按位与后赋值 | ||
^= | 按位异或后赋值 | ||
|= | 按位或后赋值 | ||
15 | , | 逗号运算符 | 从左到右 |
表 2 中优先级最高的运算符中的最后一个(类型名称){列表} 是 C99 新增加的。
一些运算符记号在表 2 中出现了两次。例如,自增运算符 ++ 和自减运算符 --,在作后缀运算符(如表达式 x++)时,较其用作前缀运算符(如表达式 ++x)时,具有较高的优先级。
+、-、* 和 & 运算符记号不但可以当作一元运算符(unary operator,只需要一个操作数),也可以当作二元运算符(binary operator,需要两个操作数)。例如,* 只有一个操作数的时候,就是间接运算符(indirection operator),而有两个操作数的时候,就是乘号。