3.10.4 摇摆的else子句
依据语法,一个if语句是由关键字“if”、圆括号、表达式和其他语句组成,这里的“其他语句”可以是任何语句,包括另一个if语句。
如果if语句的子句也是一个if语句,那可就花哨了。为了演示这种情况,我们编写了一个新版的cusum函数,它里面的if语句就是这种情况。在这个新版的函数里,if语句首先检查变量r的值是否为零,如果为零则直接结束函数的执行并返回到调用者;否则的话,它的else子句检查r的值是否大于1000000000。如果条件成立,则也结束函数的执行,将控制返回到调用者;如果不成立,则执行while语句,开始累加过程。
unsigned long long int cusum(unsigned long long int r) { unsigned long long int sum = 0; if(r == 0)return 0; else if(r > 1000000000)return 0; else while(r)sum += r --; return sum; }
在这里有两个if语句,但第二个if语句是另一个if语句的组成部分。如图3-4所示,第一个被框住的return语句是第一个if语句的第一个子句;第二个被框住部分尽管也是if语句,但它整体上是第一个if语句的else子句。
图3-4 规范的if语句在语法上是没有歧义的
但是,如果if语句嵌套不当,则容易使人迷惑。比如下面的例子,你来说说,里面的else子句到底属于第一个if语句,还是属于第二个if语句?
unsigned long long int cusum(unsigned long long int r) { unsigned long long int sum = 0;
if(r > 0) if(r <= 1000000000) while(r)sum += r --; else sum = 0; return sum; }
尽管从排版上来看,这个else子句属于第一个if语句,但真实的情况与排版无关。如图3-5所示,虽然被框住的部分是一个带有else子句的if语句,但它可以被认为是顶上那个if语句的子句(它没有else子句)。
图3-5 有歧义的if语句,这是它的第一种解读方式
然而,如图3-6所示,我们也可以认为else子句属于第一个if语句,第二个if语句没有else子句,且属于第一个if语句的第一个子句。
图3-6 有歧义的if语句,这是它的第二种解读方式
那么,到底哪种隶属关系才是正确的呢?C语言规定,一个else子句从属于离它最近的那个if语句。因此,这个else子句实际上是第二个if语句的一部分(这就是说图3-5才是正确的)。如果这并不是你所期望的,那就应该使用复合语句来明确隶属关系:
if(r > 0) { if(r <= 1000000000) while(r)sum += r --; } else sum = 0;