C语言中数据具有数据类型属性,数据类型确定了数据所占的内存空间和数据范围,那么如果超出了这个数据范围会发生什么情况呢?
比如:char a = 200;为什么输出时-56呢?
char型数据 -128的二进制为什么为1000 0000呢?
想要知道上面这些问题的答案,要从数据在内存中的存储说起。
数据在内存中的存储
C语言规定,把内存的最高位作为符号位,在符号位中,用 0 表示正数,用 1 表示负数。
在计算机内存中,整数一律采用补码的形式来存储。
原码、反码、补码
原码、反码、补码的理解
①原码
将一个整数转换成二进制形式,就是其原码。原码就是一个整数本来的二进制形式。
②反码
对于正数,它的反码就是其原码(原码和反码相同);负数的反码是将原码中除符号位以外的所有位(数值位)取反
③补码
对于正数,它的补码就是其原码(原码、反码、补码都相同);负数的补码是其反码加 1。
举例:
所以,short a = 6;存的二进制是0b0000000000000110;
而short a = -18;存的二进制是1111111111101110;
short b = 0b1111111111101110;
printf("%hd",b);
数据溢出
数据类型确定了这个空间所能盛放的数据的最大值和最小值。
以char型为例:
比如:char a;那么a的数据大小为:-2^7~2^7-1即:-128~127
unsigned char a;那么a的取值范围为:0~2^8-1 即0~255
如果使用char型存放一个200,那么就超出了char型数据所能表示的数据范围,程序会按照一定的规则将这个200转化为-128~127这个范围中的某个数后再去进行存储。
数据溢出转换规则
数据范围的表示是一个环状结构.
如果数据增长到最大值,则数据从最小值方向开始依次递增
如果数据减到最小值,则数据从最大值方向开始依次递减
①如果这个超出范围的数是正数,比如200,那么使用这个数据-256,看结果是否在-128~127范围内,如果不在继续-256,直到最后的结果在-128~127范围内。
200 - 256 = -56在-128~127范围内,则将-56存入到a中,
如果是char a = 400;400-256 = 144 > 127,则继续减256,144-256=-112 ,-112在-128~127范围内,则a中存储-112.
②如果这个超出范围内的数是负数,比如-400,那么使用这个数据+256,看结果是否在-128~127范围内,如果不在继续+256,直到最后的结果在-128~127范围内。
char a = -400;
-400 + 256 = -144,不在-128~127范围内,继续+256
-144+256 = 112,在-128~127范围内,所以a中存储的是112,而不是-400.