11-优先级和求值顺序
5.2.8 优先级和求值顺序
运算符优先级为表达式中的求值顺序提供重要的依据,但是并没有规定所有的顺序。C给语言的实现者留出选择的余地。考虑下面的语句:
y = 6 * 12 + 5 * 20;
当运算符共享一个运算对象时,优先级决定了求值顺序。例如上面的语句中, 12 是和 + 运算符的运算对象。根据运算符的优先级,乘法的优先级比加法高,所以先进行乘法运算。类似地,先对 5 进行乘法运算而不是加法运算。简而言之,先进行两个乘法运算 6 12 和 5 20 ,再进行加法运算。但是,优先级并未规定到底先进行哪一个乘法。C语言把主动权留给语言的实现者,根据不同的硬件来决定先计算前者还是后者。可能在一种硬件上采用某种方案效率更高,而在另一种硬件上采用另一种方案效率更高。无论采用哪种方案,表达式都会简化为 72 + 100 ,所以这并不影响最终的结果。但是,读者可能会根据乘法从左往右的结合律,认为应该先执行 + 运算符左边的乘法。结合律只适用于共享同一运算对象的运算符。例如,在表达式 12 / 3 2 中, / 和运算符的优先级相同,共享运算对象 3 。因此,从左往右的结合律在这种情况起作用。表达式简化为 4 2 ,即 8 (如果从右往左计算,会得到 12/6 ,即 2 ,这种情况下计算的先后顺序会影响最终的计算结果)。在该例中,两个*运算符并没有共享同一个运算对象,因此从左往右的结合律不适用于这种情况。
学以致用
接下来,我们在更复杂的示例中使用以上规则,请看程序清单5.7。
程序清单5.7 rules.c 程序
/* rules.c -- 优先级测试 */
#include <stdio.h>
int main(void)
{
int top, score;
top = score = -(2 + 5) * 6 + (4 + 3 * (2 + 3));
printf("top = %d, score = %d\n", top, score);
return 0;
}
该程序会打印什么值?先根据代码推测一下,再运行程序或阅读下面的分析来检查你的答案。
首先,圆括号的优先级最高。先计算 -(2 + 5) 6 中的圆括号部分,还是先计算 (4 + 3 (2 + 3)) 中的圆括号部分取决于具体的实现。圆括号的最高优先级意味着,在子表达式 -(2 + 5) * 6 中,先计算 (2 + 5) 的值,得 7 。然后,把一元负号应用在 7 上,得 -7 。现在,表达式是:
top = score = -7 * 6 + (4 + 3 * (2 + 3))
下一步,计算 2 + 3 的值。表达式变成:
top = score = -7 * 6 + (4 + 3 * 5)
接下来,因为圆括号中的*比+优先级高,所以表达式变成:
top = score = -7 * 6 + (4 + 15)
然后,表达式为:
top = score = -7 * 6 + 19
-7 乘以 6 后,得到下面的表达式:
top = score = -42 + 19
然后进行加法运算,得到:
top = score = -23
现在, -23 被赋值给 score ,最终 top 的值也是 -23 。记住, = 运算符的结合律是从右往左。