C++ 带符号和无符号char类型赋值超出表示范围的情况

来源:互联网 发布:合金装备经典台词知乎 编辑:程序博客网 时间:2024/04/30 14:35

在C++中字符型被分为了三种:char、signed char和unsigned char。需要的注意:

  • 字符的表现形式只有两种:带符号的和无符号的,类型char具体使用哪一种由编译器决定;
  • 如果需要使用不大的整数,应该明确指出它的类型是signed char或者unsigned char。

关于带符号类型:

  • 带符号类型在表示范围内正值和负值的量应该平衡,例如,8比特理论上应该可以表示-127至127,大多数现代计算机将实际的表示范围定位-128至127;
  • 当我们赋给带符号类型一个超出它表示范围的值时,结果是未定义的(undefined),程序可能继续工作、可能崩溃,也可能生成垃圾数据。

关于无符号类型:

  • 无符号类型中所有比特都用来存储值,例如,8比特的unsigned char可以表示0至255区间内的值;
  • 当我们赋给无符号类型一个超出它表示范围的值时,结果是初始值对无符号类型表示数值总数取模后的余数(即取模后所得的数,并不是取余)。

例如:8比特大小的unsigned char可以表示0至255区间内的值,如果我们赋了一个区间以外的值,则实际的结果是该值对256(总数)取模后所得的余数。
因此,把-1赋给8比特大小的unsigned char所得的结果是255,使用2种方法计算:

有整数a和b,a对b进行取模或取余运算
1、求整数商:c=a/b
取模运算在计算商值向负无穷方向舍弃小数位
取余运算在计算商值向0方向舍弃小数位
2、计算模或者余数:r=a-(c*b)
注:取模运算遵循尽可能让商小,取余运算遵循尽可能让余数的绝对值。因此,取模和取余的结果不同。
mod为取模,rem为取余,取模和取余所得的数在a和b同为整数的时候是相等的,因为舍弃小数位时向负无穷和向0是同一个方向。

在本例中,将-1和256带入a和b,c=-1/256,向负无穷方向舍弃小数得-1,计算得r=255.

计算机中带符号的整数采用二进制的补码进行存储
正数的补码等于其二进制编码
负数的补码等于其绝对值的二进制编码,取反,再加1
在本例中,-1的绝对值是1,二进制编码为0000 0001,取反加1就是1111 1111
unsigned是无符号数,会把1111 1111看成正数,刚好是255的二进制编码。