数据的存储(写了一部分我之前不好理解的知识)
一、整型在内存中的存储
整型在内存中表示为三种形式:原码、反码、补码
原码是整型的二进制表达,反码是原码按位取反,补码是反码加一。
计算机内存储的是整型的补码
一个例子就懂了
以 1 为例 原码为:00000000 00000000 00000000 00000001
反码为:11111111 11111111 11111111 11111110 //原码按位取反
补码为:11111111 11111111 11111111 11111111 //反码加一
二、大小端问题
之前理解的时候也看了些别人的博客,看了半天无非是以下内容
什么大端小端:
大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址
中;
小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,,保存在内存的高地
址中。
上面的说法我觉得很标准,但不太利于理解,以一个例子来解释我觉得最好
我们在计算机内存储一个整型,以十六进制表示为
0x11 22 33 44
(一个整型占四个字节)
左边是高字节,右边是低字节(可以理解为一个数的各十百千位,比如千位相对于百位就是高字节)
那么它存放在内存里有两种方式
0x11 22 33 44
转化为二进制应为:00010001 00100010 00110011 01000100
但是在编译器可以看到它在内存中是这样存放的
这是小端存放,就是上面说的把低字节放在低地址
简而言之可以理解为:以0x11 22 33 44为例,如果你看到的顺序是和它存进内存之前我们看到的样子是一样的话,那它就是大端存储,要是反了过来,就是小端存储。
三、整型提升和截断
首先还是强调计算机内存储的是补码,并且正数原码反码补码相同。
整型截断
每种数据类型所占字节数不一样,就会存在整型截断的问题
例如:char所占字节为1(八个比特位),int所占字节为4(32个比特位)
如果你将129赋给char类型变量
首先,129的二进制为
00000000 00000000 00000000 10000001 每八个比特位占一个字节
那么因为char只有一个字节的大小,于是char只拿到了129最后八个比特位10000001。
截断还是比较好理解的,那么接下来看整型提升
整型提升
整型提升方式有:有符号和无符号整型,两种提升方式
1.有符号
如果原类型是有符号(singned),符号位为1,后面高位全部补1,符号位为0,后面高位全部补0。
2.无符号
如果原类型是无符号(unsigned)的,则后面高位全部补0。
打印时
按%d打印: 有符号打印,求原码再打印
按%u打印: 无符号打印,直接打印整型截断提升后的值(就是不进行补码转换为原码的步骤)
下面以例子加强理解
char a = 129;
unsigned char b = 129;
1.printf("%d",a);打印的结果为-127
2.printf("%u",a);打印的结果为4294967169
3.printf("%d",b);打印的结果为129
那么结果为什么是这样呢?
1.
我们知道129的二进制表示为
00000000 00000000 00000000 10000001原码反码补码都是这个
当a为有符号时
截断之后为10000001
提升时高位补符号位
11111111 11111111 11111111 10000001这是补码
转换为原码打印
10000000 00000000 00000000 01111111 此时a=-127
2.
此时以无符号打印,那么129整型截断提升后的值就直接的打印出来,不转换为原码
11111111 11111111 11111111 10000001 此时a=4294967169
3.
129补码为
11111111 11111111 11111111 10000001
整型截断提升后(b为无符号数,高位补0)
00000000 00000000 00000000 10000001
然后因为是以%d打印,求整型提升后的原码打印,又因为129为正数,所以原码和补码一样,所以打印出来还是129
总而言之牢记这两步,将每种情况都对应按步骤做,总不会出错
1.有符号
如果原类型是有符号(singned),符号位为1,后面高位全部补1,符号位为0,后面高位全部补0。
2.无符号
如果原类型是无符号(unsigned)的,则后面高位全部补0。
打印时
按%d打印: 有符号打印,求原码再打印
按%u打印: 无符号打印,直接打印整型截断提升后的值(就是不进行补码转换为原码的步骤)
你学会了吗???