文章目录
一、 整形在内存中的存储
1. 整形家族:
char、 signed char、 unsigned char、 short、 unsigned short、 int、 unsigned int、 long、 unsigned long
注意:
- char 类型的数据,存储的是字符对应的 ASCII 码属于整形
- 缺省的 char 类型由编译器决定是有符号 char 还是无符号 char
- 除了 char 类型,其他类型在缺省时默认为有符号类型
类型决定了创建变量所占的字节大小,那这些字节中存储的是什么呢?
2. 整形的存储
数值之间的进制转换尚不清楚的小伙伴可移步参考 进制转换的那些事
计算机中的整形有三种二进制表示方式:原码、反码、补码
三种表示方法均有符号位和数值位两部分
用最高位表示符号位, 0 表示正数, 1 表示负数,其余位表示数值位
注意:对于无符号类型的数据,没有符号位,最高位表示数值位
对于正数
- 原码、反码、补码相同:数值转换成的二进制
对于负数:
- 原码:数值转换成的二进制
- 反码:原码符号位不变,其他位按位取反
- 补码:反码 + 1
按下 F10 调式启动后,在菜单栏中调式中的窗口中的内存可以查看数据在内存的存储
继续按下 F10 执行了这条语句后,在内存输入 &a 即可观察到下图的数据
在内存窗口显示的数据是十六进制的,四个二进制位表示一个十六进制位,不理解可以参考 进制转换的那些事
a 变量存储的是正整数,原、反、补码相同以十六进制表示如下:
- 原码:00 00 00 01
- 反码:00 00 00 01
- 补码:00 00 00 01
b 变量原码、反码、补码以十六进制表示如下:
- 原码:80 00 00 01
- 反码:ff ff ff fe
- 补码:ff ff ff ff
在内存窗口显示的数据与变量的原码、反码、补码比较,其中只有变量的补码,除了字节顺序相反之外,数值是相同的
因此:对于整形而言:数据在内存中存放的是补码
注意:为什么字节顺序是相反的呢?在本篇的大小端字节序中说明
3. signed char 和 unsigned char 的取值范围
signed char 和 unsigned char 都只占一个字节,即 8 个比特位,这 8 个 比特位的每一位都可能为 0 或 1,signed char 第一位表示符号位,unsigned char 没有符号位,都表示数值位
如果将一个大于 signed char 类型取值范围的数据存储到一个 signed char 变量中,采取的是低位截断的方式
char 和 short 类型变量所占的字节大小,小于 int 类型,运算是需要发生整形提升
- 有符号类型:高位补符号位,符号位为 1 补 1,为 0 补 0
- 无符号类型:高位补 0
二、 大小端字节序
在 内存 中是以字节为单位存储数据,自然就会产生一个问题,对于多字节的数据,int,float,存储到内存的字节顺序是如何的呢?
正整数的原、反、补码相同,为了方便易于理解,这里采用正整数来说明
小端字节序:
将数据的低位字节放在低地址处,数据的高位字节放在高地址处
这里用 VS2022 来掩饰
大端字节序:
将数据的低位字节放在高地址处,数据的高位字节放在低地址处
注意:只是数据存储在内存中的字节顺序变了,数值还是 0x12345678
三、 浮点型在内存中的存储
数据是以二进制的形式在计算机中存储的,首先应将十进制表示的浮点数转换为二进制表示的浮点数
例如: 十进制数 5.5 转换为二进制数为 101.1 (进制转换的那些事)
对于任意一个二进制浮点数 V 可以表示为如下形式:
(-1) ^ s * m *2 ^ e
(-1) ^ s 表示符号,V 为正数时,s = 0,V 为负数时 s = 1
m 表示有效数字
2 ^ e 表示指数位
根据国际标准 IEEE754,浮点数存储时,只存储符号位 S,指数 E,和有效数字 M:
-
S 和 s 相同
-
M通过 m 小数点移动表示为大于 0 小于 2 的数
- 规约浮点数:M 大于等于 1 小于 2
- 非规约浮点数:M 大于 0 小于 1
-
E 为 m 移动小数点后的 e 加上一个中间值,这个中间值为 2 ^ (b - 1) - 1 ,其中的 b 为存储指数的比特位
存储时指数 E 规定为一个无符号整数,由于 E 可能为负数,采取的方法是加上一个中间值 -
规约浮点数:当存储的 0 < E <= 2 ^ (b - 2)(E 不全为 0 或不全为 1),并且存储的 M 大于等于 1 小于 2
-
非规约浮点数:当存储的 E = 0 (E 为全 0),并且存储的 M 大于 0 小于 1
对于 32 位的浮点数,最高的 1 位表示符号位,存储 S,接着的 8 位存储指数 E,剩下的 23 位存储有效数字 M
对于 64 位的浮点数,最高的 1 位表示符号位,存储 S,接着的 11 位存储指数 E,剩下的 52 位存储有效数字 M
1. 规约浮点数存储及取出:
-
有效数字 M 不存储第一位
在规约浮点数中 M 被规定为大于等于 1,小于 2,默认 M 的第一位为 1,不存储该位,只存储后面的数字,比如:1.011 存储只存储 011 -
指数 E 存储时需要加上中间值
8 位的 E 加上 2 ^ (8 - 1) - 1 = 127,11 位的 E 加上 2 ^ (11 - 1) - 1 = 1023
对于 5.5 在内存中存储如下:
-
有效数字 M 加上第一位 1
M 取出时,加上1,比如:存储空间中 011,取出为 1.011 -
指数 E 减去中间值
8 位的 E 减去 2 ^ (8 - 1) - 1 = 127,11 位的 E 减去 2 ^ (11 - 1) - 1 = 1023
在内存中取出 5.5 如下
2. 非规约浮点数的存储及取出
-
存储和取出时:都为 M
-
存取和取出时:指数 E 加上(减去)中间值
非规约浮点数的中间值比规约浮点数的中间值小 1
3. 一些特殊值
- 当存储 E = 2 ^ (b - 1)(E 为全 1),并且存储的 M 为全 0 时
- S = 0,表示正无穷大(infinity) -> inf
- S = 1,表示负无穷大(infinity) -> -inf
- 当存储 E = 2 ^ (b - 1)(E 为全 1),并且存储的 M 不为全 0 时
- S = 0,表示为不是一个数(not a number) -> nan
- S = 1,表示为不是一个数(not a number) -> -nan
总结:
形式 | 指数 | 小数部分 |
---|---|---|
零 | 0 | 0 |
非规约形式 | 0 | 非0 |
规约形式 | 1 到 2 ^ b - 2 | 任意 |
无穷 | 2 ^ b - 1 | 0 |
nan | 2 ^ b - 1 | 非零 |