深度剖析数据在内存中的存储

一、 整形在内存中的存储

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
      数据存储
      总结:
形式指数小数部分
00
非规约形式0非0
规约形式1 到 2 ^ b - 2任意
无穷2 ^ b - 10
nan2 ^ b - 1非零
  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值