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