C语言非常道
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

3.7 认识逗号表达式

现在,让我们回到函数cusum在本章开头的原始版本:

              unsigned long long int cusum(unsigned long long int r)
              {
                  unsigned long long int n = 1, sum = 0;

                  while(n <= r)
                  {
                    sum = sum + n;
                    n = n + 1;
                  }

                  return sum;
              }

如果while语句的循环体包含了一个以上的声明和语句,使用复合语句通常是必须的选择,但如果复合语句仅由多条语句组成而没有声明,而且这些语句都是表达式语句,则依然可以不使用复合语句,而是把这些表达式用逗号“,”首尾相连,就像这样:

              while(n <= r)sum = sum + n, n = n + 1;

或者这样:

              while(n <= r)sum += n, n ++;

注意,这里的逗号“,”并不是语文里的逗号,它是C语言的一个运算符,称为“逗号运算符”。逗号运算符有一左一右两个操作数,逗号运算符和它的操作数共同组成逗号表达式,例如5, 6就是一个逗号表达式。

在所有运算符里,逗号运算符的优先级最低。所以,表达式sum += n, n ++是一个逗号表达式。这就是说,运算符+=的操作数是sum和n;运算符++的操作数是n;逗号运算符的操作数只能是sum += n的值和n++的值。

即使还不了解逗号运算符和逗号表达式的作用,我们也能通过推理发现表达式sum +=n, n ++的求值过程有问题。

我们知道,求值一个表达式包括值计算和发起一个副作用,然而并不要求它们是一个连续的过程。那么,对于逗号表达式sum += n, n ++来说,它的求值过程是怎样的呢?如果先求值sum += n,而且它的值计算和副作用在求值表达式n ++之前就能完成,这自然没什么问题,加到变量sum的值是变量n递增前的原值;但如果先求值n ++,而且它的值计算和副作用在求值sum += n之前就已经完成,那么加到变量sum的值是变量n递增后的新值,这就违背了我们的初衷和原意,将得不到正确的累加结果。

练习3.6

表达式sum = sum + n ++的值与子表达式的求值顺序无关,变量n和sum在求值完成后的新值也与子表达式的求值顺序无关,为什么?