计算的优先级和顺序

C 运算符的优先级和结合性将影响表达式中操作数的分组和计算。 仅当存在优先级较高或较低的其他运算符时,运算符的优先级才有意义。 首先计算带优先级较高的运算符的表达式。 也可以通过“绑定”一词描述优先级。 优先级较高的运算符被认为具有更严格的绑定。

下表总结了 C 运算符的优先级和结合性(计算操作数的顺序),并按照从最高优先级到最低优先级的顺序将其列出。 如果几个运算符一起出现,则其具有相同的优先级并且将根据其结合性对其进行计算。 以后缀运算符开头的部分描述了表中的运算符。 此部分的其余部分提供了有关优先级和结合性的常规信息。

C 运算符的优先级和结合性

Symbol1 运算类型 结合性
. -> 后缀 ++ 和后缀 -- Expression 从左到右
前缀 ++ 和前缀 -- sizeof & * + - ~ ! 一元 从右到左
typecasts 一元 从右到左
* / % 乘法 从左到右
+ - 加法 从左到右
<< >> 按位移动 从左到右
< > <= >= 关系 从左到右
== != 相等 从左到右
& 按位“与” 从左到右
^ 按位“异或” 从左到右
| 按位“与或”
&& 逻辑“与” 从左到右
&#124;&#124; 逻辑“或” 从左到右
? : 条件表达式 从右到左
= *= /= %=

+= -= <<= >>=&=

^= |=
简单和复合 assignment2 从右到左
顺序计算 从左到右
  1. 运算符按优先级的降序顺序列出。 如果多个运算符出现在同一行或一个组中,则它们具有相同的优先级。

  2. 所有简单的和复合的赋值运算符都有相同的优先级。

    表达式可以包含优先级相同的多个运算符。 当多个具有相同级别的这类运算符出现在表达式中时,计算将根据该运算符的结合性按从右到左或从左至右的顺序来执行。 计算的方向不影响在相同级别包括多个乘法 (\)、加法 (+) 或二进制按位 (& | ^*) 运算符的表达式结果。 语言未定义运算的顺序。 如果编译器可以保证一致的结果,则编译器可以按任意顺序随意计算此类表达式。

    只有顺序计算()、逻辑“与”(&&)、逻辑“或” (||)、条件表达式 (? :) 和函数调用运算符构成序列点,因此,确保对其操作数的计算采用特定顺序。 函数调用运算符是一组紧跟函数标识符的圆括号。 确保顺序计算运算符 (,) 按从左到右的顺序计算其操作数。 (请注意,函数调用中的逗号运算符与顺序计算运算符不同,且不提供任何此类保证。)有关详细信息,请参阅序列点

    逻辑运算符还确保按从左至右的顺序计算操作数。 但是,它们会计算确定表达式结果所需的最小数目的操作数。 这称作“短路”计算。 因此,无法计算表达式的一些操作数。 例如,在下面的表达式中

x && y++  

仅当 y++ 为 true(非零)时,才计算第二操作数 (x)。 因此,如果 y 为 false (0),则 x 不增加。

示例

以下列表显示编译器如何自动绑定多个示例表达式:

Expression 自动绑定
a & b &#124;&#124; c (a & b) &#124;&#124; c
a = b &#124;&#124; c a = (b &#124;&#124; c)
q && r &#124;&#124; s-- (q && r) &#124;&#124; 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 )  

另请参阅

C 运算符