计算的优先级和顺序
C 运算符的优先级和结合性将影响表达式中操作数的分组和计算。 仅当存在优先级较高或较低的其他运算符时,运算符的优先级才有意义。 首先计算带优先级较高的运算符的表达式。 也可以通过“绑定”一词描述优先级。优先级较高的运算符被认为具有更严格的绑定。
下表总结了 C 运算符的优先级和结合性(计算操作数的顺序),并按照从最高优先级到最低优先级的顺序将其列出。 如果几个运算符一起出现,则其具有相同的优先级并且将根据其结合性对其进行计算。 以后缀运算符开头的部分描述了表中的运算符。 此部分的其余部分提供了有关优先级和结合性的常规信息。
C 运算符的优先级和关联性
符号 1 | 操作类型 | 结合性 |
---|---|---|
[ ] ( ) . -> ++ -- (后缀) |
表达式 | 从左到右 |
sizeof & * + - ~ ! ++ -- (前缀) |
一元 | 从右到左 |
typecasts | 一元 | 从右到左 |
* / % |
乘法 | 从左到右 |
+ - |
加法 | 从左到右 |
<< >> |
按位移动 | 从左到右 |
< > <= >= |
关系 | 从左到右 |
== != |
相等 | 从左到右 |
& |
按位“与” | 从左到右 |
^ |
按位“异或” | 从左到右 |
| |
按位“与或” | 从左到右 |
&& |
逻辑“与” | 从左到右 |
|| |
逻辑“或” | 从左到右 |
? : |
条件表达式 | 从右到左 |
= *= /= %= += -= <<= >>= &= ^= |= |
简单和复合赋值 2 | 从右到左 |
, |
顺序计算 | 从左到右 |
1 运算符按优先级的降序顺序列出。 如果多个运算符出现在同一行或一个组中,则它们具有相同的优先级。
2 所有简单的和复合的赋值运算符都有相同的优先级。
表达式可以包含优先级相同的多个运算符。 当多个具有相同级别的这类运算符出现在表达式中时,计算将根据该运算符的结合性按从右到左或从左至右的顺序来执行。 计算的方向不影响在相同级别包括多个乘法 (*
)、加法 (+
) 或二进制按位(&
、|
或 ^
)运算符的表达式的结果。 语言未定义运算的顺序。 如果编译器可以保证一致的结果,则编译器可以按任意顺序随意计算此类表达式。
只有顺序计算 (,
)、逻辑“与”(&&
)、逻辑“或” (||
)、条件表达式 (? :
) 和函数调用运算符构成序列点,因此,确保对其操作数的计算采用特定顺序。 函数调用运算符是一组紧跟函数标识符的圆括号。 确保顺序计算运算符 (,
) 按从左到右的顺序计算其操作数。 (函数调用中的逗号运算符与顺序计算运算符不同,不提供任何此类保证。)有关详细信息,请参阅序列点。
逻辑运算符还确保按从左至右的顺序计算操作数。 但是,它们会计算确定表达式结果所需的最小数目的操作数。 这称作“短路”计算。 因此,无法计算表达式的一些操作数。 例如,在下面的表达式中
x && y++
仅当 y++
为 true(非零)时,才计算第二操作数 (x
)。 因此,如果 y
为 false (0),则 x
不增加。
示例
以下列表显示编译器如何自动绑定多个示例表达式:
表达式 | 自动绑定 |
---|---|
a & b || c |
(a & b) || c |
a = b || c |
a = (b || c) |
q && r || s-- |
(q && r) || s-- |
在第一个表达式中,按位“与”运算符 (&
) 的优先级高于逻辑“或”运算符 (||
) 的优先级,因此,a & b
构成了逻辑“或”运算的第一操作数。
在第二个表达式中,逻辑“或”运算符 (||
) 的优先级高于简单赋值运算符 (=
) 的优先级,因此,b || c
在赋值中分组为右操作数。 请注意,赋给 a
的值为 0 或 1。
第三个表达式显示可能会生成意外结果的格式正确的表达式。 逻辑“与”运算符 (&&
) 的优先级高于逻辑“或”运算符 (||
) 的优先级,因此,将 q && r
分组为操作数。 由于逻辑运算符确保按从左到右的顺序计算操作数,因此 q && r
先于 s--
被计算。 但是,如果 q && r
计算的结果为非零值,则不计算 s--
,并且 s
不会减少。 如果 s
未减少会导致程序出现问题,则 s--
应显示为表达式的第一操作数,或者在单独的运算中应减少 s
。
以下表达式是非法的并会在编译时生成诊断消息:
非法表达式 | 默认分组 |
---|---|
p == 0 ? p += 1: p += 2 |
( p == 0 ? p += 1 : p ) += 2 |
在此表达式中,相等运算符 (==
) 的优先级最高,因此,将 p == 0
分组为操作数。 条件表达式运算符 (? :
) 具有下一个最高级别的优先级。 其第一操作数是 p == 0
,第二操作数是 p += 1
。 但是,条件表达式运算符的最后一个操作数被视为 p
而不是 p += 2
,因为与复合赋值运算符相比,p
的匹配项将更紧密地绑定到条件表达式运算符。 由于 += 2
没有左操作数,因此发生语法错误。 您应使用括号以防止此类错误发生并生成可读性更高的代码。 例如,可以按如下所示使用括号来更正和阐明前面的示例:
( p == 0 ) ? ( p += 1 ) : ( p += 2 )