数据在内存中的存储(打入“内部”深度剖析哦)

news2024/11/28 14:18:35

  前面的文章介绍中,只对整数在内存中的存储进行了简单介绍,可是只了解这么一点点是远远不够的呢,这篇文章呢就对数据在内存中的存储的几个重难点进行了详细的介绍哦,希望对爱学习的小伙伴们有所帮助~

目录

一.数据类型

二.大小端介绍

三.整型在内存中的存储

四.浮点数在内存中的存储


一.数据类型

  在C语言中基本的内置类型有:

char:字符数据类型      short:短整型            int:长整型      long:长整型

long long:更长的整型    float:单精度浮点数      double:双精度浮点数

  那在C语言中有没有字符串类型呢? 在C语言中其实是没有string类型的,因为字符串是通过字符数组来进行存储的。 

这些基本的内置类型所占的字节给大家插张表格,大家看吧,这样清晰明了一点~

类型的意义:

(1)避免浪费内存以防止内存不够用;

(2)解决存进去的问题,决定使用某个类型得知道所需要开辟的内存空间的大小;

(3)解决取出来的问题,改变看内存的视角,可以一个一个类型一个类型的看,而不一定一个比特位一个比特位的看。

   世间万物都需要分类,当然,这里的类型也是归类的。

 类型可以分为:

(1)整型家族:

 (2)浮点数家族

float 、 double

(3)构造类型(自定义类型)

数组类型  结构体类型(struct) 枚举类型(enum) 联合类型(union) 

小编在网上照了一张构造类型的框架图,大家可以看看哦~ 

(4)指针类型

int *pi  、char *pc、float *pf 、void *pv

 (5)空类型

void 表示空类型(无类型)

通常应用于函数的返回类型,函数的参数,指针类型

二.大小端介绍

为何会有大小端这个术语呢?这其中还是有个小故事的,在《格列佛游记》中有样子有讲到两个国家因为吃鸡蛋是从鸡蛋的大端吃还是从鸡蛋的小端吃而争执,还引起了战争,是不是听到这个故事,感觉没必要呢,想着只要把鸡蛋迟到肚子里就好了呀,哈哈哈,但是,反过来想,要不是这些人拥有一颗好奇心以及坚信自己的观点,我们学到的知识术语为何如此形象呢?

 好啦,说了这么多,该进入正题啦~

因为小编在学习C语言的途中,使用的是VS2019,所以,这里我们以VS2019编译器的使用为例,进行下面的介绍。

前面讲的那个小故事是说大小端这个术语的由来,那在学习过程中它的由来是?

(一)引入大小端

  作为一名程序员,总不能只会写代码,而不擅长调试吧,那么,在调试的过程中,或许你会发现让你意想不到的结果出现哦,接下来进入主题喽~

看这个运行结果截图,我们可以发现在编译器中的存储方式是和我们读出来的存储方式是相反的,那为什么会出现这种情况?我们该如何理解以及解释这种情况呢?不会是编译器出bug了吧,哈哈哈,这可不敢乱下结论哦,接着看…… 

(二)大小端是什么?

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

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

通俗地讲:就是倒着存就是小端模式,顺着存,就是大端模式。

那为什么会有大小端呢?

理由:因为在计算机系统中,我们是以字节为单位的,每个地址单元它都对应着一个字节,而我们都知道,一个字节是8bit位,但是在C语言中除了8bit位的char之外,还有16bit位的short,32bit位的long类型(不过这里得看编译器),另外,对于位数大于8位的处理器,比如说16位或者32位的处理器,由于寄存器的宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题,从而就导致了大端存储模式和小端存储模式。

我们知道,存储方式有大端和小端两种方式,前面也讲了,倒着存就是小端模式,顺着存,就是大端模式。所以,接下来,举个简单的例子给大家看吧,帮助大家理解~

下面这是代码实现~ 

通过运行结果,我们再次说明了,在vs2019编译器中是以小端模式存储的。

假如深入内存内部又是怎么样的呢?

注意:

(1)因为大小端是把数据放在内存之后才会有的,所以不能直接对变量进行类型强制转换;

(2)char类型只有一个字节,是没有大小端问题的,大小端指的是以字节为单位的顺序; 

   通过前面的介绍,大家应该对编译器的大小端存储有了一个相对的了解吧,常说眼里过千遍,不如手里过一遍,写代码一样,看别人演示,别人讲是一回事,自己实操是另外一回事,大家可以在自己的编译器上试试,希望关于大小端的介绍可以对大家在学习这部分内容的时候有一定的帮助吆~ 

三.整型在内存中的存储

  C语言都学习到这里啦,想必大家应该知道在C语言中整型是四个字节,也就是32bite吧,在内存中就是一个32位的二进制数字。

那原码,反码,补码分别是什么呢,它们又是如何求的呢?

这三种二进制表示方法,都由符号位和数值位两部分组成,当是正数时,符号位为0;当是负数时,符号位为1;

原码:就是将一个整数转换成二进制的形式,通俗的讲,原码就是一个整数原有的不做任何改变的二进制形式。

反码:在原码的基础上,将原码的符号位不变,其他位按位取反,就可以得到反码。

补码:在反码的基础上,反码加1,就可以得到补码。

举个例子吧:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
    int m = 10;
    //00000000000000000000000000001010  
    //正数的原码,反码,补码是相同的;
    int m = -10;
    //10000000000000000000000000001010  -- 原码
    //11111111111111111111111111110101  -- 反码
    //11111111111111111111111111110110  -- 补码
 
    return 0;
}

  在计算机内部,整数的存储采用的是以补码的方式进行存储,那么,当读取整数时,还需要采用逆向转换的思想,通俗的讲,就是要将补码转换成原码。

四.浮点数在内存中的存储

  前面讲过整数在内存中的存储方式了,接下来我们就讨论浮点数在内存中又是如何存储的?

(一)浮点数的表示方法

国际标准IEEE规定(电气和电子工程协会)754,任意一个二进制浮点数V可以表示成下面的形式:

a:(-1)^S * M * 2^E

注:当S = 0时,V为正数;

       当S = 1时,V为负数;

       M表示有效数字;

       2^E表示指数;

说明:

(1)这里有效数字范围是[1,2),大家在学习计算机知识的过程中如果对二进制不熟悉,我们就可以拿从小接触到大的十进制进行类比,这样就可以很容易理解啦。

(2)指数部分以2为底数,同样的道理,类比十进制中指数部分是以10为底数的。

举个例子:

(2)浮点数在内存中的存储

根据标准规定:

a:对于32位的浮点数(float型)

最高的一位是符号位S,接下里8位是指数E,剩下的23位为有效数字M。

b:对于64位的浮点数(double型)

最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M。 

这里分开做几点说明:

1、符号位S

对于符号位S,只有0和1两种情况,分别表示正和负;

2、有效数字M

 对于有效数字M,由于M的范围是[1,2),也就是说M的整数部分一定为1,所以IEEE754标准规定:在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的小数部分。比如保存1.01的时候,只保存小数部分01,而将整数部分的 1会舍去,等到要读取的时候,再把第一位的1加上去就好啦。这么做的目的就是,可以节省1位有效数字。32位浮点数留给M只有23位,将第一位舍去后,就可以保存24位有效数字,可以使数据的精度更高一些。

3.指数部分E(相对复杂)

指数部分E是一个无符号整数(unsigned int)。

如果E为8位(32位浮点型),那么E能表示的范围是0 ~ 255;

如果E为11位(64位浮点型),那么E能表示的范围是0 ~ 2047。

当然,这个指数E也可以为负,但unsigned int的类型使E为非负数,所以IEEE754标准规定,存入内存中时,真实的指数必须加上一个中间值:

单精度:(8位的时候):这个中间数是127

双精度:(11位的时候):这个中间数是1023

这是规定,大家没必要再去深究为何是这样哦~

指数在内存中取出还分三种情况:

(1)E不全为0或1

规则:指数E的计算值减去127/1023,得到真实值,然后再将有效数字M前加上第一位的1就好啦

举个列子:

对于浮点数5.0:前面分析了,S= 0,M = 1.01,这里需要将M小数点前面的整数去掉,然后把小数部分的01进行存储,后面不够的位数全部用0补齐,然后E= 2,这使,需要加上+127==>129,然后转换成2进制,再进行存储,所以,5.0表示为2进制为:

0 10000001 0100000000000000000000

(2)E全为0

当E加上后127为全0,那么换个说法就是说E的真实值其实是 -127,即该浮点数指数部分是2 ^ (-127),显然这是一个很小很小的数,那么此时有效数字M不再加上第一位的1,而是还原为以0为整数的小数。这样做是为了表示 ± 0,以及接近于0的很小的数字。

(3)E全为1

当E加上后127为全1,那么换个说法就是说E的真实值其实是 128,即该浮点数指数部分是2 ^ (128),显然这是一个很大很大的数,此时表示正负无穷大(正负号由S决定)。

   好啦,关于数据在内存中的存储详细介绍在这里就画上圆满的句号啦,希望对大家能够有帮助,看完的话,动一下可爱的小指头来个小心心吧。如果在阅读的过程中发现错误之处,欢迎大家评论区留言吖~

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/620378.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Protobuf速成指南】Message中如何定义“数组”?

文章目录 2.0一、字段规则1.1 规则1.2 改进1.3 消息类型作为字段类型 二、repeated字段使用方式三、Contact2.01.write.cc2.read.cc3. 查看二进制信息①hexdump② --decode选项 2.0 本系列文章将通过对通讯录项目的不断完善&#xff0c;带大家由浅入深的学习Protobuf的使用。这…

win10的另一种美化字体的方式,使用noMeiryoUI

目录 1. 前提2. 字体选择3. 查看已经安装的字体并查看效果4. 安装软件修改系统字体5. 修改浏览器字体 1. 前提 21年的时候写了一篇文章&#xff0c;《Windows10下美化字体&#xff0c;达到类似mac的效果》&#xff0c;当时还很迷恋macType这个软件的使用&#xff0c;觉得好牛逼…

Linux——安装VMwaretools实现文件共享功能

作为一个Linux初学者&#xff0c;应该熟悉相关的文件下载和安装以及简单的配置命令&#xff0c;下面通过安装一个VMwaretools来实现window环境和Linux环境下文件的共享功能的实现。 一、安装VMwaretools 点击重新安装后&#xff0c;会在桌面上看到有一个光盘&#xff0c;则代表…

单片机的基础知识和原理

单片机是一种集成了中央处理器&#xff08;CPU&#xff09;、内存、输入/输出&#xff08;I/O&#xff09;端口和其他外设的小型计算机系统。它通常用于嵌入式系统&#xff0c;如家电、汽车电子、工业控制等领域。 下面是单片机的基础知识和原理的概述&#xff1a; 架构&…

Linux系统安装——VMware15.5安装centos7.6 (附资料下载+联网配置+踩坑总结)

一、安装虚拟机VMware15.5 VMware虚拟机安装Win10&#xff0c;安装包秘钥/系统镜像/激活工具如下&#xff1a;(主要这个地址不限速&#xff0c;方便&#xff01;) https://www.123pan.com/s/g520Vv-Dg2id (遇到会拦截下载任务的浏览器&#xff0c;直接换浏览器下载即可&#xf…

【LVS负载均衡群集】

目录 一、企业群集应用概述1、群集的含义2、企业群集分类3、负载均衡群集架构1、负载均衡的结构2、负载均衡群集工作模式分析 二、LVS的三种工作模式1、NAT 模式地址转换 2、TUN模式IP隧道 3、DR模式直接路由 三、实战NAT模式 LVS负载均衡群集部署1.部署共享存储&#xff08;NF…

将安全性置于首位:考试系统源码的安全漏洞和防护措施

在当今数字化时代&#xff0c;考试系统源码的安全性已经成为了一个至关重要的问题。随着更多人开始远程学习和在线考试&#xff0c;考试系统的安全漏洞也越来越容易被利用。因此&#xff0c;在开发和使用考试系统源码应用程序时&#xff0c;保护用户数据和系统资源免受攻击是至…

思维导图整理,100个好看实用的模板分享

思维导图是一款有效提升工作和生活效率的生产力工具&#xff0c;受到全球千万用户的喜爱。 它帮助我们将所需的信息以图形的形式呈现&#xff0c;更加便于我们的记忆。头脑风暴帮助我们捕捉灵感&#xff0c;激发 我们更多的想象力。 它可以应用在我们生活以及工作的方方面面。项…

卡尔曼滤波与组合导航原理(七)平方根Kalman滤波:Potter平方根滤波、SVD分解滤波、UD分解滤波、平方根信息滤波SRIKF

文章目录 一、平方根滤波基本形式二、Potter平方根滤波1、方差阵的量测更新2、方差阵的时间更新3、Potter平方根滤波流程4、向量量测情况下的方差阵量测更新 三、奇异值&#xff08;SVD&#xff09;分解滤波1、时间更新方差方程的SVD分解2、量测更新方差方程的SVD分解3、SVD分解…

西电网课雨课堂《书法鉴赏》全部课后答案

声明&#xff1a;本文CSDN作者原创投稿文章&#xff0c;未经许可禁止任何形式的转载&#xff0c;原文链接 如果图片挂了&#xff0c;可以移步至我的博客西电网课雨课堂《书法鉴赏》答案 - 小木槌 文章目录 绪论--解惑初学书法者&#xff08;上&#xff09;绪论--解惑初学书法者…

Es elasticsearch 十八 Logstash 数据抽取工具

目录 基础 启动命令 简单配置文件 控制台输入输出打印 input从log文件获取数据-如分布式日志收集 监听端口 filter过滤器 Grok 正则捕获 Output 输出到es 文件输入 es输出 获取日志中字段 level 基础 从原数据 获取数据 发送到 某地方 Input{} filter{} output{} …

JMeter 常用的几种断言方法,你会几种呢?

在使用Jmeter进行性能测试或者接口自动化测试工作中&#xff0c;经常会用到的一个功能&#xff0c;就是断言。断言是在请求的返回层面增加一层判断机制。因为请求成功了&#xff0c;并不代表结果一定正确&#xff0c;因此需要判断机制提高测试准确性。本文 主要介绍3种常用的断…

【LSTM】读取时间序列数据 | 时间序列数据的小批量划分方法

由于序列数据本质上是连续的&#xff0c;因此我们在处理数据时需要解决这个问题。当序列过长而不能被模型一次性全部处理时&#xff0c;我们希望能拆分这样的序列以便模型方便读取。 Q&#xff1a;怎样随机生成一个具有n个时间步的mini batch的特征和标签&#xff1f; A&…

4.2 Spark SQL数据源 - 基本操作

一、默认数据源 案例演示读取Parquet文件 查看Spark的样例数据文件users.parquet 1、在Spark Shell中演示 启动Spark Shell 查看数据帧内容 查看数据帧模式 对数据帧指定列进行查询&#xff0c;查询结果依然是数据帧&#xff0c;然后通过write成员的save()方法写入HDF…

还在为开发难度发愁?这个低代码平台能让你轻松搞定!

随着数字技术的不断发展&#xff0c;数字化也越来越深入人们的日常生活中&#xff0c;在这样的时代背景下&#xff0c;企业是需要通过不断创新来满足用户日益增长的业务需求。 使用背景 对企业而言&#xff0c;随着组织规模的扩大&#xff0c;各种业务流程系统需要持续而快速地…

浮点数的存储方式和取值范围

一、有符号整型的编码方式 1. 真值 把用""、"-"表示符号&#xff0c;数值部分用绝对值的编码的表示方式称为真值。 如3用4bit真值表示为0011&#xff0c;-1用真值表示为-0011。 2. 原码 符号位为0表示正数&#xff0c;符号位为1表示负数&#xff0c;数…

网络安全的究竟如何自学?

以十五派9年信息安全教育经验以及数千名学生摸索实践可以得知&#xff0c;在知乎上能够搜索到这个问题的人不外乎三种人&#xff1a; 第一种人在找网络安全入门的捷径&#xff1b; 第二种人想自己的方向进而获得认同感&#xff1b; 第三种人是已经在自学网络安全但是过程中碰…

卡尔曼滤波与组合导航原理(九)Sage-Husa自适应滤波

自适应滤波有很多种方式&#xff0c;也很实用 一、自适应滤波基本思想 函数模型 { X k Φ k / k − 1 X k − 1 Γ k − 1 W k − 1 Z k H k X k V k \left\{\begin{array}{l} \boldsymbol{X}_{k}\boldsymbol{\Phi}_{k / k-1} \boldsymbol{X}_{k-1}\boldsymbol{\Gamma}_{…

Mujoco xml编写(二)

目录 .1 运行 1.1 测试 .2 XML 2,1 基础 2.3 简单实例 2.3 进阶例子 .1 运行 1.1 测试 基于Mujoco210 Ubuntu 22.04配置安装_啥也不是的py人的博客-CSDN博客完成安装后 import mujoco_py import os mj_path mujoco_py.utils.discover_mujoco() xml_path os.path.join…

学习并深入理解闭包

前言 学习闭包前&#xff0c;先学点别的。 程序执行时&#xff1a; 1.编译阶段 创建变量对象GO&#xff0c;包括变量和函数作用域装在一块内存中。但是没有赋值&#xff0c;变量都是undefined,函数&#xff1a;0xxx 2.创建执行上下文 里面有VO对应ao(函数里的变量&#xff0…