IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    C陷阱与缺陷之“悬挂”else

    TacuLee发表于 2015-12-15 07:40:48
    love 0

    考虑下面的程序段:

    if(x==0)
    	if(y==0) error();
    else{
    	z = x + y;
    	f(&z);
    }

    这段代码中编程者的本意是应该有两种主要情况,x等于0以及x不等于0.对于x等于0的情况,除非y也等于0(此时调用函数error),否则程序不作任何处理;对于x不等于0的情形,程序首先先将x与y之后赋值给z,然后以z的地址为参数来调用函数f。

    然而,这段代码实际上所做的与编程者的意图相去甚远。原因在于C语言中有这样的规则,else始终与同一括号内最近的未匹配的if结合。如果我们按照上面这段程序实际上被执行的逻辑来调整代码缩进,大致是这个样子:

    if(x==0){
    	if(y==0) 
    		error();
    	else{
    		z = x + y;
    		f(&z);
    	}
    }

    也就是说,如果x不等于0,程序将不会做任何处理。如果要得到原来的例子中由代码缩进体现的编程者本意的结果,应该这样写:

    if(x==0){
    	if(y==0) 
    		error();
    }
    else{
    	z = x + y;
    	f(&z);
    }

    现在,else与第一个if结合,即使它离第二个if更近也是如此,因为此时第二个if已经被括号“封装”起来了。

    有的程序设计语言在if语言中使用收尾定界来显式地说明。例如,在Algol68语言中,前面提到的例子可以这样写:

    if x = 0
    then if y = 0
    	then error
    	if
    else z := x + y;
    	f(z)
    fi

    像上面这样强制使用收尾定办符完全避免了“悬挂”else的问题,付出的代价则是程序稍稍变长了一点。有些C程序员通过宏定义也能达到类似的效果:

    #define IF {if(
    #define THEN ){
    #define ELSE }else{
    #define FI {{

    这样,上例中的C程序就可以写成

    IF x == 0
    THEN IF y ==0
    	THEN error();
    	FI
    ELSE z = x + y;
    f(&z);
    FI

    如果一个C程序员过去不是长期浸淫于Algol 68语言,他会发现上面这段代码难于卒读。这样一种解决方案所带来的问题可能比它所解决的问题还要糟糕。

    未经允许不得转载:TacuLee » C陷阱与缺陷之“悬挂”else



沪ICP备19023445号-2号
友情链接