数据在内存中的存储

目录

前言

1.数据类型的介绍

2.  整形在内存中的存储

2.1 原码、反码、补码

2.2 大小端

3. 浮点型在内存中的存储

 4.结语


前言

 在本文,我会详细介绍数据类型,整形在内存中的储存,大小端字节序,浮点型在内存中的存储。话不多说,我们直接进入正题。

1.数据类型的介绍

 我们都知道基本的数据类型:

char        字符数据类型         1字节
short       短整型                    2字节
int         整形                          4字节
long        长整型                    4/8字节
long long   更长的整形          8字节
float       单精度浮点数          4字节
double      双精度浮点数       8字节

 进行一下分类的话有

整形类:                                                                                               浮点型类:

char    char里面存储的是ASCII码值,所以本质上是整形。                  float
           unsigned char                                                                            double
           signed char
short
           unsigned short [int]
           signed short [int]
int
           unsigned int
           signed int
long
           unsigned long [int]
           signed long [int]
以及一些其他类型,这里不再举例。
unsigned类型与unsigned类型的区别
宏观上,unsigned类型没有负数,而signed类型可以表示正负数。
为什么会有这样的结果呢?
整形数据在内存中是以二进制数来存储的,最高一位称为符号位,最高位是1表示为负数,最高位是0表示正数。而unsigned类型二进制所有数位均为有效位,没有符号位,所以比signed类型能存储更大的数据,但是同时也丧失了表示正负数的能力!!!
上面说到整形数据在内存中以二进制数进行存储,这样的一串二进制序列,我们称为补码。

2.  整形在内存中的存储

2.1 原码、反码、补码

例如数字 9 ,他的二进制数为 ab17bcc6252f45d595b48b264fbd8d0a.png
// 如果不懂二进制转换的,可以去百度一下,这里不过多赘述。
这样直接转换而成的二进制数列,成为原码。如果存储在int中,要在前头补28个0,使其有32位。
原码 的符号位不变,其他位 按位取反(1变0,0变1),即可得到反码。这里是0110。
反码 加一 即可得到补码。这里是0111。
这里可以再举例 -1:
456f9af8a6e4409eb0bc300c4df8ec85.png   从上往下分别是原码,反码,补码

 5eedd91b182d41ab8693ee2c767235b3.png

 温馨提示:

16进制中两个数字一个字节

二进制8个数字代表一个字节

299271a6d28b4062bf87f355cf77d975.png

为什么我们不直接使用原码而要使用补码储存在内存中呢??

在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统
一处理;
同时,加法和减法也可以统一处理( CPU 只有加法器)此外,补码与原码相互转换,其运算过程
是相同的,不需要额外的硬件电路。

因为原码与补码的转换遵循同一套规则:符号位不变,其他位按位取反,加1。

所以转换效率也不会低。

值得注意的是

下面我们来一道例题,具体讲解一下原码,反码,补码的实际运用。

//输出什么?
#include <stdio.h>
int main()
{
    char a= -1;
    signed char b=-1;
    unsigned char c=-1;
    printf("a=%d,b=%d,c=%d",a,b,c);
    return 0;
}

 建议大家先自己尝试做一遍再看以下解析:

打印出a = -1;b = -1; c = 255;

a与b情况一致:

开始:-1 二进制:补码 11111111111111111111111111111111

存char: 截断(留下右边):11111111

用%d打印,整形提升,看a的类型是char,有符号位(高位补符号位的数):

补码:111111111111111111111111111111111111

打印出来给人看(原码):1000000000000000000000000000001

计算得:-1。

c:

开始:-1 二进制:补码 11111111111111111111111111111111

存unsigned char: 截断(留下右边):11111111

用%d打印,整形提升,看a的类型是unsigned char,无符号位(高位补0):

补码:00000000000000000000000011111111

打印出来给人看(原码):0000000000000000000000011111111

算出来是255.

截断的规则是:高位截断,低位保留!!正负数均适用!!!

2.2 大小端

99a3278f983644e2a674dd417f774778.png

 我们把a以16进制储存在内存中,发现a存储的字节序有些不太对劲。数据是反向存储的,这是怎么回事呢?

以10进制举例,1234,从4到1,数位从低到高。

那么11223344,44 33 22 11 的数位依次增高。

52067dcddd3c4c34a4bbdf2ea17e412c.png

从地址上看,44 33 22 11 的地址越来越高。

像这样,低地址存低数位,高地址存高数位,我们称为小端存储。大端存储反之。

什么是大小端:

大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址
中;
小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,,保存在内存的高地
址中。

 一般来说,PC机绝大部分都是小端存储。

这里简单了解一下即可。

3. 浮点型在内存中的存储

int main()
{
 int n = 9;
 float *pFloat = (float *)&n;
 printf("n的值为:%d\n",n);
 printf("*pFloat的值为:%f\n",*pFloat);
 *pFloat = 9.0;
 printf("num的值为:%d\n",n);
 printf("*pFloat的值为:%f\n",*pFloat);
 return 0;
}

 我们先引入一个例子来说明。

8a54a63e720444deb2179a32470da72c.png

 为什么会出现以上这种情况呢?

与整形的存储不同,浮点型有他自己的规则。

根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数V可以表示成下面的形式:
  • (-1)^S * M * 2^E
  • (-1)^S表示符号位,当S=0,V为正数;当S=1,V为负数。
  • M表示有效数字,大于等于1,小于2。
  • 2^E表示指数位。

 硬啃定义肯定是难以理解的,我们以 5.5 这个数字来举例:

5 的二进制序列是 101

0.5 表示为 2^(-1) ,二进制中为 0.1

5.5 即可表示为 101.1。

使用科学计数法 1.011 * 2^2

因为是正数,符号位为0: (-1)^ 0

整体写成最终公式 (-1)^ 0 * 1.011 * 2^2    

S = 0; M = 011; E = 2;

然后将得到的 最终公式 转化为二进制序列,方法如下:

浮点数的二进制序列:(补码)

先存S(0或1)然后分类型1.float 存 (E +127)转化成二进制序列

                                           2.double 存 (E+1024)转化成二进制序列

最后存 M(去掉整数位1,剩下的数字直接拉进序列)

不够32位,在后边补0.

//去掉整数位1是为了提高一位的精度,之后使用时他会自动补1回来!!

为什么不补2,3?因为是二进制序列!!!

285ea6c78e1e44ebae1ebe55a162d328.png

先存0(S),再存10000001(2+127),接着存011,最后给尾巴补0;

输出时:类型1:E不为全0,不为全1

再举例:

这里的9是以浮点型的形式放进一个整形,所以会有以下转化,如果是以int放进n,则原码取反+1转补码

e913e38ae21b4f7bb7e8b0ace0537bd6.png

将数字转化成浮点型举例:

9.0

首先将9转化成原码:1001

转化成科学技术法:1.001 * 2^3 (E存进内存时是127+3=130>>10000010)

符号位加上:(-1)^ 0 * 1.001 * 2^3

写成码:0 10000010 001 00000000000000000000 (001是1.001去1存有效数字)

解释一下为什么要将有效数字减1,因为这样可以获得更大的精度!

到这里,相信大家已经了解了浮点型的存储方式!附上二图

d1903316938947849780a90dad874a8d.png

0cceea71a2b64756a021bee922753d08.png

 4.结语

 本文到这里已经对数据在内存中的存储做出了常见的讲解,可以说应该是十分周尽了,另外还有一些特例与细节不一一列举,因为可能不会经常遇到。如果喜欢本文,请给博主一个三连吧!!

关注我,一起进步!!!!

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Laxinues

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值