C语言中微妙的bug(一)

来源:互联网 发布:pkpm加密狗 淘宝 编辑:程序博客网 时间:2024/05/22 00:46

  一、摘自《C专家编程_1.10 “安静的改变”究竟有多少安静》

     类型转换。

     在下面这个例子里,变量d下标值小1,这段代码的母的就是处理这种情况。但if表达式的值却不是真。为什么?是不是有Bug:

         

int array[] = { 23, 34, 12, 17, 204, 99, 16 };#define TOTAL_ELEMENTS (sizeof(array)/sizeof(array[0]))main(){       int d = -1, x;       /* ... */              if(d <= TOTAL_ELEMENTS - 2)               x = array[d+1];       /* ... */}

    TOTAL_ELEMENTS所定义的值是unsigned int类型(因为sizeof()的返回类型是无符号类型数)。if语句在signed int和unsigned int之间测试相等性,所以d被升级为unsigned int类型,-1转换成unsigned int的结果将是一个非常巨大的正整数,致使表达式的值为假。这个bug在ANSI C中存在,而如果K&K C的某种编译器的sizeof()的返回值是无符号数,那么这个Bug也存在。要修正这个问题,只要对TOTAL_ELEMENTS进行强制类型转换即可:

if(d < (int)TOTAL_ELEMENTS - 2)
        对无符号类型的建议

    尽量不要在你的代码中使用无符号类型,以免增加不必要的复杂性。尤其是,不要仅仅因为无符号不存在负值(如年龄、国债)而用它来表示数量。

    尽量使用像int那样的有符号数类型,这样在涉及升级混合类型的复杂细节时,不必担心边界情况(如-1被翻译为非常大的正数)

    只有在使用位段和二进制掩码时,才可以使用无符号数。应该在表达式中使用强制类型转换,使操作数均为有符号数或者无符号数,这样就不必由编译器来选择结果的类型。 

二、switch的另外一个问题-----break中断了什么

    测试代码:

    

 1 #include<stdio.h> 2  3 int main() 4 { 5     int a = 2, b = 0; 6     switch(a) 7     { 8         case 1: 9               b = 1; 10               break; 11         case 2: 12               if(2 == a) 13               { 14                  break;(这里的break的意图是跳到16行) 15               } 16               b = 2;(意图是跳到这里) 17               break; 18         default: 19               b = 3; 20  21     }(但事实上是直接跳到这里了) 22     printf("b=%d\n",b); 23  24         return 0; 25 }
       运行结果:b=0;

       这个bug导致了,AT&T导致了整个长话网络的瘫痪。

0 0
原创粉丝点击