一、优先级
考虑下面的代码:
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
请按任意键继续. . .
来源:CSDN
作者:兲涳
链接:https://blog.csdn.net/u014411348/article/details/104059342