美文网首页C/C++经验技巧总结
使用无符号类型要特别注意

使用无符号类型要特别注意

作者: XDgbh | 来源:发表于2018-01-14 23:30 被阅读2次

一个由无符号类型引发的微妙的错误

#include <stdio.h>  
#include  <string.h>

int main()
{
    char array[] = "hello";
    int d = -1, x;
    //(1)//if (d <= sizeof(array) / sizeof(char))    
    //(2)//if (d <= strlen(array))

    //if (d <= (int)sizeof(array) / sizeof(char))    /*输出:x = 104*/     
    if (d <= (int)strlen(array))        /*输出:x = 104*/
    {
        x = array[d + 1];
        printf("x = %d\n", x);  //字符'h'对应的ASCII码是104,   'a'是97
    }
    else
    {
        printf("sizeof(array) / sizeof(char) = %u\n", sizeof(array) / sizeof(char));
        printf("strlen(array) = %u\n", strlen(array));  
      //用%d输出也是一样,都是正数
    }

    return 0;
}
  • 这个程序若用(1)或(2)的判断条件会输出:
    sizeof(array) / sizeof(char) = 6
    strlen(array) = 5
    加上强制类型转换(int)才会输出:x = 104

(1)原因是sizeof操作符(注意它不是一个函数,也可以有 sizeof char;sizeof(char);效果一样)的返回值类型是size_t,而typedef unsigned int size_t;
所以在执行表达式d <= sizeof(array)/sizeof(char)时,右边表达式结果为无符号整型6,因此会将左边的整型d装换成无符号整型(-1(在计算机中以1的补码形式存在为二进制1111...11111)将变成变成一个超级大的整数),因此判断结果是false。

改正方法:d <= (int)sizeof(array)/sizeof(char),人为增加强制类型转换,这样就不必由编译器来选择结果的类型了。

(2)同理,strlen()函数的返回值类型也是size_t,而typedef unsigned int size_t;。但是注意strlen()函数和sizeof操作符的区别,sizeof会多计算一个结束符'\0'的大小,因此会多1,而strlen()函数总是只计算实际字符串字符个数。

改正方法:d <= (int)strlen(array),人为增加强制类型转换,这样就不必由编译器来选择结果的类型了。

对无符号类型的建议(《C专家编程》第24页)

1、尽量不要在代码中使用无符号类型,以免增加不必要的麻烦,尤其是,不要仅仅因为无符号类型不存在负值(如年龄)而用它来表示数量,可以多增加if-else判断数量的合法性也比用无符号类型更安全。否则一个int的 -1,由编译器自动升级成无符号型int,将会变成一个非常大的数。
2、如果用了,应该在表达式中使用强制类型转换,使操作数均为有符号或者无符号类型,这样就不必由编译器来选择结果的类型,可以避免微妙的错误发生。
3、只有在使用位段和二进制掩码时,最好去用无符号数。这里就要谈到正数和负数在计算机中的二进制存储方式了。正数简单,就是原码二进制形式存储,如int型32bit位 int a = 1;那么a在计算机中存储为二进制000...(总共31个0)...0001。但是负数就比较复杂,要用原码求反码再加1得到的补码的二进制形式存储在计算机中,如int b = -1;原码和a一样,反码就是111...(总共31个1)...1110,然后反码加1得到补码111...(总共32个1)...1111。可见b并不是简单的存储为二进制100...(总共30个0)...0001。因此在使用位段和二进制掩码这些需要按bit位操作的情况下,为了在使用时让我们脑子里想的和计算机处理的一致,尽量都用无符号类型,就可以避免负数在计算机中的特殊存储方式带来的影响。
《注意:负数要以10进制输出时,又要将计算机中存储的补码,先减1求得反码,再按位求反得到原码,然后将原码转换成10进制输出并在前面添加一个‘-’号》

使用无符号类型的优缺点

  • 比如int类型和unsigned int类型,同样是占用4字节(32bit位),int类型的取值范围是(-2^31到2^31),而unsigned int类型的取值范围是(0到2^32),可见在利用正数的这一半时无符号数的可用范围是有符号的两倍。有符号数最高bit位的0或1只能表示+-符号,不能表示数值,浪费了。

相关文章

  • 使用无符号类型要特别注意

    一个由无符号类型引发的微妙的错误 这个程序若用(1)或(2)的判断条件会输出:sizeof(array) / si...

  • Guava-原生类型

    无符号和有符号 在计算机中,可以区分正负的类型,称为有符号类型,无正负的类型,称为无符号类型。 概述 Java的原...

  • 0318-数据选项(+encoding等

    int: unsigned:符号 zero fill:会自动使用无符号位指的是位数固定,如果数值长度不足字段类型的...

  • Java无符号数据类型处理

    1、无符号与有符号对比: ​ 下面以Byte字节类型举例: ​ 有符号类型数据 符号位 ...

  • Java的无符号类型移位

    Java的原始类型里没有无符号类型,如果需要某个宽度的无符号类型,可以用>>>,这个是java的无符号右移操作符,...

  • 03-Swift中的数据类型

    整数类型# Swift 提供了8,16,32和64位的有符号和无符号整数类型。一般使用Int就可以了 浮点型# 浮...

  • 《C#编程入门》04-C#数据类型

    常用数据类型 有符号整数类型:sbyte short int long 无符号整数类型:byte ush...

  • [MySQL 之二] 数据类型

    1、数值类型 (1)整型 整数类型字节最小值最大值TINYINT1有符号-27无符号 0有符号 27-1无符号 2...

  • 数据类型之字符型

    字符类型(char):字符,字母和符号 char类型:表示16位的无符号整数(无负数,只有正数)或者Unicode...

  • 003 带符号类型和无符号类型

    除去布尔型和扩展的字符型之外,其他整型可以划分为带符号的(signed)和无符号的(unsigned)两种。带符号...

网友评论

    本文标题:使用无符号类型要特别注意

    本文链接:https://www.haomeiwen.com/subject/lunloxtx.html