整形数据的存储,补码的三种计算方式,这些你都懂吗?
目录
首先要明白整形家族的分类,和基础知识。(32位下)
原反补的计算
数据在内存中的存储
一些实例
首先要明白整形家族的分类,和基础知识。(32位下)
类型 | char | int | short | long |
字节个数 | 1 | 4 | 2 | 4 |
取值范围 | -128~127 | -2^30~2^30-1 | -2^14~2^14-1 | -2^30~2^30-1 |
类型 | unsigned char | unsigned int | unsigned short | unsigned long |
字节 | 1 | 4 | 2 | 4 |
取值 | 0~255 | 0~2^31-1 | 0~2^15-1 |
0~2^31-1 |
原反补的计算
计算机中的整数有三种表示方法,即原码、反码和补码。三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位 负整数的三种表示方法各不相同。
原码 :就是把数据按照正负数形式翻译为2进制即可。
反码 :就是原码的符号位不变,其他的按照比特位按位取反即可。
补码 :就是原码+1得到补码,符号位也要参与计算 。
正数的原码,反码,补码一样。
那么由补码怎么得出原码呢?
方法1
把原码反码的过程逆序下。这个是最常见的,就不在举例子了。
方法2
int b = -15;
原 :10000000 00000000 00000000 00001111
反: 11111111 11111111 11111111 111110000
补 :11111111 11111111 11111111 11110001
补码在按位取反:10000000 00000000 00000000 00001110
补码在按位取反:10000000 00000000 00000000 00001111
方法3
int c = -14;
原 :10000000 00000000 00000000 00001110
反 :11111111 11111111 11111111 11110001
补:11111111 11111111 11111111 11110010
从右向左找出第一个1,然后把从右向左到符号位之间的全都按位取反。
补:11111111 11111111 11111111 11110010
取反:10000000 00000000 00000000 00001110
(红色字体是按规则取反)
数据在内存中的存储
对于整形数据而言,在内存中是以补码形式存储的。
那么怎么放入呢?
比如 int a = 1;
补码为 :00000000000000000000000000000001
16进制显示为00 00 00 01,是怎么放进去呢?
一般常见的有两种 。
00 00 00 01 或者 01 00 00 00
其中01的部分称为数据的低权值位。
权值:就像是10进制中的个位的1就没十位上的1表示的大一样,根本原因是权值的原因
数据的低权值位放在低地址处是小端存储。
数据的低权值位放在高地址处是大端存储。
这个图是小端存储。
为什么要有补码?
在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统 一处理; 同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程 是相同的,不需要额外的硬件电路。
简单来说:就是为了方便减法,不用借位。
一些实例
例 1:
int a = 1;
int b = -1;
相加为0,这很简单,那么用补码的形式来运算下。
a 原/反/补:00000000 00000000 00000000 00000001
b原:10000000 00000000 00000000 00000001
b反:11111111 11111111 11111111 11111110
b补:11111111 11111111 11111111 11111111
a补+b补 为
1 00000000 00000000 00000000 0000000 一共33位比特位,但是int只有32位比特位呀。
所以就发生截断,那么会截断那个比特位呢?是截断那个1呢?还是截断最后一个0呢?
这样来看,截断的是最高的比特位,留下的是最低的32位比特位。
例 2:
unsigned int a = -1;printf("%u\n",a);printf("%d\n",a);
这样可以数据存进去吗?
答案是可以的,因为数据存储时不会考虑类型,你只是把数据的补码存入开辟好的空间中就可以了,至于类型什么时候用呢?其实是在读取数据时才起作用,输出时,因为是有符号数输出,所以内存中存的数据11111111 11111111 11111111 11111111以有符号打印。是-1,以无符号打印是2^31-1.
例3:
char a = -128;printf("%u\n", a);
这样打印结果是什么呢?
首先a的补码是1000000 因为%u是unsigned int,a是char,所以a要进行整形提升,%u是无符号,所以补位补最高位,变成11111111 11111111 11111111 10000000,打印为4294967168。
例 4:
char a = 127;printf("%d", a);
这样打印结果呢?
首先a是char,原反补一样是 01111111,%d是int,所以对a进行整形提升,补位时补符号位0,
变成00000000 00000000 00000000 01111111打印是127
今天的补充内容是为了明天的移位符进行铺垫,今天就到这里。
明天见~~~