计算的优先级和顺序

C 运算符的优先级和关联性会影响表达式中作数的分组和计算。 仅当存在优先级较高或较低优先级的其他运算符时,运算符的优先级才有意义。 首先计算优先级较高的运算符的表达式。 优先级也可以由单词“binding”来描述。据说优先级较高的运算符具有更严格的绑定。

下表汇总了 C 运算符的优先级和关联性(作数的计算顺序),按优先级从高到低的顺序列出它们。 如果多个运算符一起出现,则它们具有相等的优先级,并根据它们的关联性进行评估。 表中的运算符在以 后缀运算符开头的各节中介绍。 本部分的其余部分提供有关优先级和关联性的一般信息。

C 运算符的优先级和关联性

符号 1 操作类型 结合性
[ ] ( ) . ->
++ -- (后缀)
表达式 从左到右
sizeof & * + - ~ !
++ -- (前缀)
一元 从右到左
typecasts 一元 从右到左
* / % 乘法性的 从左到右
+ - 累加性 从左到右
<< >> 按位移位 从左到右
< > <= >= 关系 从左到右
== != 平等 从左到右
& Bitwise-AND 从左到右
^ Bitwise-exclusive-OR 从左到右
| Bitwise-inclusive-OR 从左到右
&& Logical-AND 从左到右
|| Logical-OR 从左到右
? : Conditional-expression 从右到左
= *= /= %=
+= -= <<= >>= &=
^= |=
简单和复合赋值 2 从右到左
, 顺序评估 从左到右

1 运算符按优先顺序降序列出。 如果多个运算符出现在同一行或组中,则它们具有相等的优先级。

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

表达式可以包含多个优先级相等的运算符。 当多个此类运算符出现在表达式中的同一级别时,计算会根据运算符的关联性(从右到左或从左到右)进行。 计算方向不会影响在同一级别包含多个乘法()、加法(*或二元位(+&|^运算符的表达式结果。 作顺序不是由语言定义的。 如果编译器可以保证一致的结果,编译器可以按任意顺序计算此类表达式。

只有顺序求值()、logical-AND(,&&)、logical-OR(||)、条件表达式(? :)和函数调用运算符构成序列点,因此保证其作数的特定计算顺序。 函数调用运算符是函数标识符后面的括号集。 保证顺序求值运算符 (,) 从左到右计算其作数。 (函数调用中的逗号运算符与顺序计算运算符不同,不提供任何此类保证。有关详细信息,请参阅 序列点

逻辑运算符还保证从左到右计算其作数。 但是,它们计算确定表达式结果所需的最小作数。 这称为“短路”评估。 因此,可能无法计算表达式的某些作数。 例如,在表达式中

x && y++

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

例子

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

表达式 自动绑定
a & b || c (a & b) || c
a = b || c a = (b || c)
q && r || s-- (q && r) || s--

在第一个表达式中,按位 AND 运算符 (&) 的优先级高于逻辑 OR 运算符 (||),因此 a & b 形成逻辑 OR 运算的第一个作数。

在第二个表达式中,逻辑 OR 运算符 (||) 的优先级高于简单赋值运算符(=),因此 b || c 分组为赋值中的右侧作数。 请注意,分配给 a 的值是 0 或 1。

第三个表达式显示可能生成意外结果的正确格式表达式。 logical-AND 运算符 (&&) 的优先级高于逻辑 OR 运算符 (||),因此 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 运算符