6.1 运算符优先级

一、优先级

考虑下面的代码:

butter = 25.0 + 60.0 * n / SCALE;

这条语句中有加法、乘法和除法运算。先算哪一个?是25.0加上60.0,然后把计算的和85.0乘以n,再把结果除以SCALE?还是60.0乘以n,然后把计算的结果加上25.0,最后再把结果除以SCALE?还是其他运算顺序?假设n是6.0,SCALE是2.0,带入语句中计算会发现,第1种顺序得到的结果是255,第2种顺序得到的结果是192.5。C程序一定是采用了其他的运算顺序,因为程序运行该语句后,butter的值是205.0。

显然,执行各种操作的顺序很重要。C 语言对此有明确的规定,通过运算符优先级来解决操作顺序的问题。每个运算符都有自己的优先级。正如普通的算术运算那样,乘法和除法的优先级比加法和减法高,所以先执行乘法和除法。如果两个运算符的优先级相同怎么办?如果它们处理同一个运算对象,则根据它们在语句中出现的顺序来执行。对大多数运算符而言,这种情况都是按从左到右的顺序进行(=运算符除外)。因此,语句:

butter = 25.0 + 60.0 * n / SCALE;

的运算顺序是:

60.0  *  n    首先计算表达式中的*或/(假设n的值是6,所以60.0*n得360.0)

360.0 / SCALE  然后计算表达式中第2个*或/

25.0 + 180     最后计算表达式里第1个+或-,结果为205.0(假设SCALE的值是2.0)

许多人喜欢用表达式树(expression tree)来表示求值的顺序,如图5.3所示。该图演示了如何从最初的表达式逐步简化为一个值。

如何让加法运算在乘法运算之前执行?可以这样做:(建议自己写代码时要使用

flour = (25.0 + 60.0 * n) / SCALE;

最先执行圆括号中的部分。圆括号内部按正常的规则执行。该例中,先执行乘法运算,再执行加法运算。执行完圆括号内的表达式后,用运算结果除以SCALE。

下表总结了到目前为止学过的运算符优先级。(从低至高)

注意正号(加号)和负号(减号)的两种不同用法。结合律栏列出了运算符如何与运算对象结合。例如,一元负号与它右侧的量相结合,在除法中用除号左侧的运算对象除以右侧的运算对象。

 

二、求值顺序

运算符优先级为表达式中的求值顺序提供重要的依据,但是并没有规定所有的顺序。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,这种情况下计算的先后顺序会影响最终的计算结果)。在该例中,两个*运算符并没有共享同一个运算对象,因此从左往右的结合律不适用于这种情况。

老规矩,看个程序清单:

/************************************************************************
功能:优先级测试                                                                      
************************************************************************/
#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);
	system("pause");
	return 0;
}

程序的运行结果如下:

top = -23, score = -23
请按任意键继续. . .

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值