无符号整型能产生哪些bug?

描述

为什么不建议使用无符号整型,无符号整型能产生哪些bug?

  《C专家编程》有这么几行代码。

#include 


int array[] = {23, 34, 12, 17, 204, 99, 16};
#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))


int main()
{
    int d = -1, x;
    /* ... */


    if (d <= TOTAL_ELEMENTS - 2)
        x = array[d + 1]; 
    /* ... */


    return 0;
}
  一个数组,一个宏定义,宏的作用就是计算数组的元素个数。

主函数里面d初始化成-1,判断语句中用 d 跟 TOTAL_ELEMENTS - 2做比较,如果成立,则给 x 赋值。

代码很简单,乍一看,-1 确实小于 5,于是判断语句肯定成立。


问题就出在了这边。


d属于有符号整型,TOTAL_ELEMENTS因为是sizeof的求值结果,所以它属于无符号整型,把这两个放在一起运算,很显然属于混合运算。


一个是有符号一个是无符号,编译器默认把有符号数转换成无符号数,接下来我们可以算一下。

-1的二进制是这样的:
10000000 00000000 00000000 00000001
 

因为负数在内存中是以补码的形式存放,所以先转换成反码,再转换成补码。
11111111 11111111 11111111 11111110
11111111 11111111 11111111 11111111
 

把它转换成无符号数字,就是最高位不再表示符号位,全部用来表示实际大小。

借助下计算器,-1转换成无符号数就是这么大:
4294967295
 

所以判断语句肯定不成立。
只要编译器的sizeof返回的是无符号整型,那么这个bug就一直存在。 嵌入式  

对无符号类型的建议:

 

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

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

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

 

嵌入式开发中使用无符号的场景很多,操作地址、寄存器等等,尤其是做单片机等等一些底层开发,随处可见 unsigned 字样,这也是由硬件特性决定。使用的时候多加注意,尤其是做一些基本运算的时候。

  审核编辑:汤梓红

 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分