大小端字节序
小端:数字的低位存到内存的低地址上。
大端:数字的低位存到内存的高地址上。
_大端字节序符合平时直觉,一台机器大端还是小端,取决于CPU_
int a = 0x11223344
低地址 | 0x100 | 0x101 | 0x102 | 0x103 | 高地址 |
---|---|---|---|---|---|
低地址 | 44 | 33 | 22 | 11 | 小端 |
低地址 | 11 | 22 | 33 | 44 | 大端 |
原码反码与补码
例如-10:
1000 0000 0000 0000 0000 0000 0000 1010 原码
1111 1111 1111 1111 1111 1111 1111 0101反码
1111 1111 1111 1111 1111 1111 1111 0110补码(原码取反再加一,得到补码)
计算机采用补码来存储,肯定要比直接用原码麻烦,付出这样的代价是为了让计算机的硬件 设备实现起来更简单,通过补码的方式,能够把二进制的加减法统一成加法运算
例如:
计算 0 - 1 => 0 + (-1)
1000 0000 0000 0000 0000 0000 0000 0001 -1的原码
1111 1111 1111 1111 1111 1111 1111 1110 ,-1的反码
1111 1111 1111 1111 1111 1111 1111 1111 , -1的补码
计算 2-1 2+(-1)
1111 1111 1111 1111 1111 1111 1111 1111 ,-1的补码
1000 0000 0000 0000 0000 0000 0000 0010 ,2的补码(正数的原码反码补码都一样)
「对于负数来说,需要把原码转成补码在储存,也需要用到补码转原码」
「原码转补码是 取反+1」
「补码转原码还是 取反+1」
关于char类型的一些问题
char 一个字节的变量,当按照\%d打印的时候,就会把char隐式转换成int类型的变量,再打印
1000 0001 -1的原码
1111 1110 -1的反码
1111 1111 -1的补码
\%d打印的时候就先将a先隐式转换成int
这个转换过程中,高位的三个字节也要填充,按照符号为来填充(如果a的符号位是0,高位就补0;反之补1)
此时
char => int
1111 1111 => 1111 1111 1111 1111 1111 1111 1111 1111 => -1的补码
高位补1也就是为了防止出现这样转换过程中出现数据错误的情况
1111 1111 -1在内存中的存储 unsigned char 存的还是八个1,此时最高位的1 不再是符号位了,八个1理解成正数(不考虑符号位)的结果就是255,\%d打印时,1111 1111 => 高位补0(unsigned char没有符号位)
0000 0000 0000 0000 0000 0000 1111 1111
char的范围:-128 => +127
128 转化成二进制
1000 0000 0000 0000 0000 0000 1000 0000 -128原码
1111 1111 1111 1111 1111 1111 0111 1111 -128反码
1111 1111 1111 1111 1111 1111 1000 0000 -128补码
Char a = -128
1000 0000
👇
1111 1111 1111 1111 1111 1111 1000 0000(int)
👇
1111 1111 1111 1111 1111 1111 1000 0000(unsigned int)
此时最高位不再是符号位,不再表示负数,被理解成了一个很大的数字
128 内存中的二进制表示方式
0000 0000 0000 0000 0000 0000 1000 0000 (int)
Char a =128;
1000 0000
发生了截断
导致唯一的一个1阴差阳错的成了符号位,此时a的本质上是-128