1.2.3 运算符的优先级
表达式sum = sum + n是令人迷惑的,因为这里涉及两个运算符,而且中间那个子表达式sum夹在这两个运算符之间,它到底是哪个运算符的操作数呢?它究竟跟谁是一伙的呢?
这就涉及运算符的优先级了。运算符的优先级决定了谁才能优先与它旁边的操作数结合,也决定了表达式的类别。因为C语言规定运算符“+”的优先级比“=”高,所以中间的那个sum是“+”的操作数,而不是“=”的操作数。在这种情况下,运算符“=”的操作数只能是sum和sum + n的值,所以表达式sum = sum + n本质上是一个赋值表达式,其作用是将表达式sum + n的值赋予左值sum。
二元运算符+和-称为加性运算符,“二元运算符”的意思是需要两个操作数。加性运算符用于组成加性表达式,例如103 + 266或者500-78。
加性运算符的功能是将左右两个操作数的值相加或者相减,从而得出一个结果。对于上述子表达式sum + n来说,sum和n都是左值,两个左值是无法相加的,所以都必须进行左值转换,转换为它们所代表的那个变量的存储值。
相加的结果作为运算符=的右操作数,被赋给左值sum,这将改变它所代表的那个变量的存储值。如果变量n的原值是1,变量sum的原值是0,则语句
sum = sum + n;
执行后,变量n的值仍旧是1,而变量sum的值则从原来的0变为1。
再来看表达式n = n + 1,基于相同的原因,运算符+的操作数是n和1,而运算符=的操作数则是n和子表达式n + 1的值。
对于子表达式n + 1来说,n是左值,无法用一个左值和1相加,所以n要进行左值转换,转换为它所指示的变量的存储值。然后,相加的结果作为运算符=的右操作数,被赋给左值n,这将改变它所代表的那个变量的存储值。如果变量n的原值是1,则语句
n = n + 1;
执行后,变量n的值是2。
现在,让我们来看一下这个while语句的工作过程。为了方便阅读起见,这里列出程序的全部内容(到目前为止):
unsigned long long int n, sum; n = 1; sum = 0; while (n <= 100) { sum = sum + n; n = n + 1; }
注意,这里面的空行和缩进并不是必须的,而仅仅是为了方便阅读做的排版,对程序的功能和将来的运行无任何影响。
当while语句执行的时候,先要计算表达式n<= 100的值,但这又要先计算表达式n的值(左值转换),也就是用变量n的存储值来代替这里的表达式n。
接着,用表达式n的值和100进行比较。因为刚开始的时候,n的存储值为1,这个小于等于的关系成立,表达式n<= 100的值为1,所以要执行循环体(复合语句)。
先是执行
sum = sum + n;
刚开始的时候,变量sum的存储值为0,所以表达式sum + n的值为1。紧接着,这个1被写入变量sum。
接着执行语句
n = n + 1;
第一次执行的时候,变量n的存储值为1,所以表达式n + 1的值为2,并被写入变量n,使得它的存储值变为2。
至此,while语句的循环体执行完毕。注意,每当程序的执行到达循环体尾部,都将再次回到while语句的起始处,重新判断循环条件,也就是重新计算控制表达式n<= 100的值。此时,变量n的存储值为2,依然符合小于等于100的条件,再次执行循环体。
后面的执行过程都大同小异,每次循环后,变量n的存储值都比前一次大1,而变量sum的存储值都会在原先的基础上和变量n的值累加,这和我们用手工做是一样的。
最后,变量n的存储值会递增到101,此时,表达式n<= 100的值为0,不再执行while语句的循环体,而是退出while语句,继续往后执行。当然,后面的内容尚未给出,但很快就会揭晓。