数据在内存中的存储
整数
整数在内存中都是以补码的形式存放的
正数:正数的原码、反码、补码都相同。
负数:
原码 符号位是1,其余位和绝对值对应的正数相同。
反码 除符号位以外按位取反。
补码 反码加1。(所以负数在内存中的存储是对应的正数按位取反然后加1)
例如
1 | (32位操作系统) |
浮点数
浮点数=(−1)^S × M × 2^E
- 符号位 S 当 s = 0,为正数, s = 1 为负数。
- 尾数,有效数字 M,值大于等于1,小于2,一般化为规范小数的形式,即最高位为(个位)必须为1(即1.xxxx的形式),因此不存储个位,这样精度可以进一步增加。
- 指数 E,也称作阶码,因为指数部分有正有负,但E本身为无符号数,并且为了更高的精度,所以采用移位存储(更简单的来说,即把-126~+127的数字转换为1~254范围内的移码来表示,所以阶码E = 指数(真正值) + 127(1023))。
关于指数:
- 计算机表示的阶码 = E(数值上的指数)-一个中间数。对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023,即阶码偏移量。这个就是移码的表示形式。
即计算机存储值 = 真正的指数 - 中间数, 真正的指数 = 计算机存储值 + 中间数。
这是针对于阶码(计算机存储值)非全0或者非全1的表示方法(所以范围是1-254)。 - E全为0。这时,浮点数的指数E等于1-127(或者1-1023),有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。
- E全为1。这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);如果有效数字M不全为0,表示这个数不是一个数(NaN)。
单精度 float(32位)
下标序号 31 23-30 0-22
表示内容 符号 阶码 尾数
占位数 1 8 23
双精度 double(64位)
下标序号 63 52-62 0-51
表示内容 符号 阶码 尾数
占位数 1 11 52
类型 | 长度 | 符号位 | 阶码 | 尾数 | 阶码范围 | 阶码偏移量 | 浮点数范围 |
---|---|---|---|---|---|---|---|
float | 32 | 1 | 8 | 23 | -126~+127 | +127 | 10^−38−10^+38 |
double | 64 | 1 | 11 | 52 | -1022~+1023 | +1023 | 10^−308−10^+308 |
例如
1 | 1. |
字节序
字节序即数据在内存中存储的顺序,有主机字节序(又叫CPU字节序)和网络字节序。
主机字节序
不是由操作系统决定的,而是由CPU指令集决定的,主要分为两种:
大端字节序: 高序字节存储在低位内存地址,低序字节存储在高位地址。
小端字节序: 高序字节存储在高位内存地址,低序字节存储在低位地址。
存储方式:
32位整数0x12345678,存放起始地址为0x00:
内存地址 | 0x00 | 0x01 | 0x02 | 0x03 |
---|---|---|---|---|
大端 | 12 | 34 | 56 | 78 |
小端 | 78 | 56 | 34 | 12 |
1 | // 判断大端小端 |
1 |
|
各架构处理器的字节序
* x86(Intel、AMD)、MOS Technology 6502、Z80、VAX、PDP-11 等处理器为小端序;
* Motorola 6800、Motorola 68000、PowerPC 970、System/370、SPARC(除 V9 外)等处理器为大端序;
* ARM(默认小端序)、PowerPC(除 PowerPC 970 外)、DEC Alpha、SPARC V9、MIPS、PA-RISC 及 IA64 的字节序是可配置的。
网络字节序
网络字节序是TCP/IP中规定好的一种数据表示格式,与具体的CPU类型和操作系统无关,从而能保证数据在不同的主机之间可以正确被解释。
网络字节序采用大端排列方式。