数据在内存的存储

整数在内存中的存储

       我们来回顾一下,整数在计算机是以补码的形式进行存储的,整数分为正整数和负整数,正整数的原码、反码和补码是一样的,负整数的原码、反码和补码略有不同(反码是原码除符号位,其他位按位取反(即0变成1,1变成0),补码就是反码+1),负整数的补码变为反码也就是一样的,先+1,保留符号位,其他位按位取反就可以得到原码。
       在计算机储存数据的时候,会有一个符号位(最开头的数位用1来表示负数,用0来表示正数)来表示正负,剩下的是数值位来表示数值。正数的原码、反码和补码是完全一样的,这里注意符号位是不会变的,负数的反码就是除了原码的符号位不变之外,其他位按位取反(就是0变成1,1变成0),补码就是在反码的基础上加1
这里我们以32位机器来举例:

大小端字节序

       我们来引入一个例子

大家是不是看到存储的数据是倒过来的,当数据超过一个字节的时候就会出现字节存储的顺序问题,这就是大小端字节序存储的问题。

解释

大端字节序就是数据的高位存到低地址处,低位存到高地址处。
小端字节序就是数据的低位存到低地址处,高位存到高地址处。

我们以从左到右是从低地址到高地址进行增加为例:

由此可见,开始我们引入的例子是按小端存储的,我是用VS2022来演示的。

练习

问题一

设计代码来判断当前机器的字节序

我们可以使用一个数字来进行判断,这里我使用数字1,数字1的十六进制表示为0x00000001,我们只要拿出第一个字节就可以判断大小端存储了,如果拿出的是0,就是大端字节序存储,如果拿出的是1,那就是小端字节序存储。

#include <stdio.h>int check_sys()
{int i = 1;return (*(char*)&i);
}int main()
{int ret = check_sys();if (ret == 1){printf("⼩端\n");}else{printf("⼤端\n");}return 0;
}

代码分析题

代码一
#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;
}

我们来分析一下这段代码,首先char有没有符号取决于编译器的,我这里使用的是VS2022,char是有符号的,所以a和b 就会打印-1,但是c 就不一样,首先-1在内存中的原码是10000001,反码是11111110,补码是11111111,由于 c 是无符号的,所以在内存中的11111111的第一个1就不会解读为符号位,而是正常的数位,所以打印255。

来看一下运行结果:

代码二
#include <stdio.h>int main()
{char a = -128;printf("%u\n", a);return 0;
}

首先 -128 写出二进制为1000 0000 0000 0000 0000 0000 1000 0000,反码为1111 1111 1111 1111 1111 1111 0111 1111,补码为1111 1111 1111 1111 1111 1111 1000 0000,由于是char 类型,所以发生截断,以八个比特位来进行保存,就是1000 0000,以%u的形式打印,%u是无符号的整型(就是unsigned int 类型),所以发生整型提升,就变成1111 1111 1111 1111 1111 1111 1000 0000,这个数字我们拿计算机算一下,就会得出

来看一下运行结果:

代码三
#include <stdio.h>int main()
{char a = 128;printf("%u\n", a);return 0;
}

128 的原码是 0000 0000 0000 0000 0000 0000 1000 0000,由于是整数,所以原码反码补码是一样的。由于是char 类型发生截断,保留八个比特位,就是1000 0000,用%u来进行打印,发生整型提升,由于char 是有符号的,所以提升为1111 1111 1111 1111 1111 1111 1000 0000 ,然后打印,由于是无符号的整数打印,其实结果和上一道题目的结果是一样的。

代码四
#include <stdio.h>
#include <string.h>int main()
{char a[1000];int i;for (i = 0; i < 1000; i++){a[i] = -1 - i;}printf("%d", strlen(a));return 0;
}

这个我们就要思考 char 是有取值范围的,-128~127,一共有256个数字,strlen遇到\0,就会停止计算,这里的a从-1开始存储,当a变为-128时,再减一就会变成127,一直减到0,之后减一变为-1,依次类推形成一个循环结构,就如下图所示,所以,strlen(a)的计算结果应该是0之前的255个数。

来验证一下:

代码五
#include <stdio.h>unsigned char i = 0;int main()
{for (i = 0; i <= 255; i++){printf("hello world\n");}return 0;
}

这个代码还是一样,拿出我们的循环图:

当 i 从 1 开始,加到255时,再加1 就不是256,而是255,所以不会跳出循环,而是一个死循环。

代码六
#include <stdio.h>int main()
{unsigned int i;for (i = 9; i >= 0; i--){printf("%u\n", i);}return 0;
}

这个代码其实不用画循环图也能做,因为unsigned int 是无符号的整数,i 永远大于等于0,所以这还是一个死循环。

代码七
#include <stdio.h>//x86环境,小端字节序存储int main()
{int a[4] = { 1, 2, 3, 4 };int* ptr1 = (int*)(&a + 1);int* ptr2 = (int*)((int)a + 1);printf("%x,%x", ptr1[-1], *ptr2);return 0;
}

先看ptr1:

&a取出的是整个数组的地址,&a+1是跳过整个数组,ptr1[-1] = (ptr+(-1)),由于prt1是int类型的,所以ptr1-1就会往后移动一个int,解引用就是指向 4

ptr2:
由于是小端字节序存储,我们来画一下内存图:

由于a 是数组首元素的地址,所以 a 其实指向 1 ,由于(int) a 强制类型将a转换为int类型,+1后就是a的地址+1,指向01后面的00,由于ptr2是int*类型,搜易解引用就会取出四个字节的数据,也就是0x02 00 00 00

浮点数在内存中的存储

       首先我们要知道浮点数的存储和整数的存储是不一样的,不信的可以看一下下面的运行截图:

现在我们来探讨一下浮点数在内存中是如何存储的:
由于浮点数的存储比较复杂,为了方便大家快速了解,我对此进行了一下总结:
首先,一个公式:(-1)^S * M * 2^E, 浮点数也是有符号的,所以我们用S来控制(-1)的几次方进而也就控制了浮点数的正负性,然后就是我们将浮点数化成类似科学计数法的形式(在二进制里,我们化成1.xxxx*2^E), 之后我们去掉1留下的来的xxxxx就是M,而E的处理就有点复杂,因为E可能为负数,所以为了避免负数的情况我们将其加上一个中间数(127或者1023)

注意了:浮点数的二进制表示,如0.5,怎么表示小数部分,要注意小数点后面浮点数的二进制权重是从2(-1)、2(-2)、2(-3)…依次叠加的,所以我们要凑出0.5,也就是1,因为1*2(-1)就是0.5

我们来看一下32位的float和64位的double存储情形:

E加中间数也是根据浮点数的类型进行加的,32的float加127,64位的double 加1023

正常情况下:

E不为全0或全1,那就是正常处理,减去中间数,取出S得到正负,取出M再加1得到一个1.xxxx,然后通过公式(-1)^S * M * 2^E

特殊情况:

当E位全0:
当E为全0的时候,在float下,E就是-127;在 double 下,E就是-1023,那么2^E就是一个很小的数,接近0

当E为全1:
当E为全1时,E就是一个很大的数,2^E就会使这个浮点数接近无穷大。

现在我们来分析一下开头的例子:

#include <stdio.h>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;
}

9 的原码是0000 0000 0000 0000 0000 0000 0000 1001
32位的float,S是0,E是取八位 0000 0000 ,M是000 0000 0000 0000 0000 1001,由于E为全0,所以浮点数无限接近0。

9.0 用浮点数的公式表示:先算出M来,9.0 转化为二进制 1001.0,变为科学计数法就是1.0010 * 2^3 ,则M 为001,后面凑0,知道凑满23位,E等于3+127=130,化成二进制就是
1000 0010 ,由于是整数,所以符号位取0。

所以在内存中9.0表示为:
0100 0001 0001 0000 0000 0000 0000 0000

由于要进行整数打印,将上面一串二进制直接翻译成整数,拿计算机一算:

结果就是我们打印的结果。

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

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

相关文章

【九】【算法分析与设计】双指针(3)

15. 三数之和 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请 你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含重复的三元…

echarts实践总结(常用一):柱状图(特点:渐变色、点击缩放、左右滑动、悬浮展示样式)

目录 第一章 echarts基本使用 第二章 echarts实践——柱状图 效果展示 第一章 echarts基本使用 Echarts常用配置项(详细入门)_echarts配置项手册-CSDN博客 第二章 echarts实践——柱状图 最近接到这么一个需求&#xff0c;需要画页面&#xff0c;然后有这么几个echarts的图需…

【网络安全】0xhacked CTF 大赛题解出炉啦!

此次 0xhacked CTF 比赛&#xff0c;ChainSecLabs 取得了第四名的成绩。让我们来看看比赛题目的题解吧。&#xff08;题目代码仓库在文末哦~&#xff09; BabyOtter 这是应该说是一个算法题&#xff0c;很明显需要溢出&#xff0c;因为精度问题&#xff0c;uint256(-1)/0x1…

m4v是什么文件格式?m4v视频用什么软件打开?

m4v文件格式的诞生可追溯到苹果公司。作为数字媒体领域的先锋&#xff0c;苹果在iTunes商店中为视频内容引入了m4v格式。其初衷是为了在保证视频质量的同时&#xff0c;通过管理系统&#xff0c;实现对数字内容的保护。这使得m4v成为iOS和macOS平台上广泛使用的视频格式。 M4V的…

工具精灵--超级好用的在线工具网站

工具精灵是一个超级好用的在线工具网站&#xff0c;它有这些功能&#xff1a;json格式化、xml格式化、markdown在线编辑、sql格式化、json转Java、xml转Java等。 虽然有很多这种类似的网站了&#xff0c;但它们并不好用&#xff0c;很粗糙。工具精灵超级好用&#xff0c;细节方…

为什么要为 App 应用加固 ?如何为 App 应用加固 ?

一&#xff1a;为什么要为 App 应用加固 来看下 腾讯开放平台 官方的解释说明 若应用不做任何安全防护&#xff0c;极易被病毒植入、广告替换、支付渠道篡改、钓鱼、信息劫持等&#xff0c;严重侵害开发者的利益。 App 加固后&#xff0c;可以对应用进行安全防护&#xff0c;防…

回归测试?

1. 什么是回归测试&#xff08;Regression Testing&#xff09; 回归测试是一个系统的质量控制过程&#xff0c;用于验证最近对软件的更改或更新是否无意中引入了新错误或对以前的功能方面产生了负面影响&#xff08;比如你在家中安装了新的空调系统&#xff0c;发现虽然新的空…

抛弃Superhuman?这些替代方案让你眼前一亮!

Superhuman是一个极好的人工智能工具在电子邮件助理领域。根据SimilarWeb的最新统计&#xff0c;它在全球网站排名中排名第21980位&#xff0c;月访问量为1751798。然而市场上还有许多其他优秀的选择。为了帮助您找到最适合您需求的解决方案&#xff0c;我们为您精心挑选了10种…

项目性能优化—使用JMeter压测SpringBoot项目

我们的压力测试架构图如下&#xff1a; 配置JMeter 在JMeter的bin目录&#xff0c;双击jmeter.bat 新建一个测试计划&#xff0c;并右键添加线程组&#xff1a; 进行配置 一共会发生4万次请求。 ctrl s保存&#xff1b; 添加http请求&#xff1a; 配置http请求&#xff1a;…

免费开源、支持自建服务的团队协作、个人学习文档管理系统

大家好&#xff0c;我是小麦。今天来给大家分享的是几款个人使用过的免费、开源、适合团队协作的文档管理工具&#xff0c;并且是完全支持自己搭建服务的文档管理系统。 相信大家在学习、办公等场景下对文档管理工具使用的场景是比较多的&#xff0c;例如技术开发手册、个人学…

SpringBoot(数据库操作 + druid监控功能)

文章目录 1.JDBC HikariDataSource&#xff08;SpringBoot2默认数据源&#xff09;1.数据库表设计2.引入依赖 pom.xml3.配置数据源参数 application.yml4.编写一个bean&#xff0c;映射表5.编写测试类来完成测试1.引入依赖 pom.xml2.使用JdbcTemplate进行测试3.成功&#xff0…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的交通信号灯识别系统(深度学习+UI界面+训练数据集+Python代码)

摘要&#xff1a;本研究详细介绍了一种采用深度学习技术的交通信号灯识别系统&#xff0c;该系统集成了最新的YOLOv8算法&#xff0c;并与YOLOv7、YOLOv6、YOLOv5等早期算法进行了性能评估对比。该系统能够在各种媒介——包括图像、视频文件、实时视频流及批量文件中——准确地…

Python从COCO数据集中抽取某类别的数据

1、问题描述 今天需要训练一个人工智能检测模型&#xff0c;用于检测图片或视频中的人。自行收集训练数据费时费力&#xff0c;因而选择从公开数据集COCO中进行抽取。 2、数据准备 2.1 下载 COCO2017 数据集 train:http://images.cocodataset.org/zips/train2017.zip valid…

2023年蓝桥杯省赛——幸运数字

目录 题目链接&#xff1a;0幸运数字 - 蓝桥云课 (lanqiao.cn) 解法 思路 高级思路 总结 题目链接&#xff1a;0幸运数字 - 蓝桥云课 (lanqiao.cn) 解法 首先是我写了差不多一个小时的解法&#xff0c;裂开了&#xff0c;为什么我如此废物 思路 寻找第2023个在二进制、八…

http协议的历史与基本概念

文章目录 历史和发展起源&#xff1a;HTTP/0.9&#xff08;1991年&#xff09;&#xff1a;HTTP/1.0&#xff08;1996年&#xff0c;RFC 1945&#xff09;&#xff1a;HTTP/1.1&#xff08;1997年&#xff0c;RFC 2068&#xff1b;1999年更新为RFC 2616&#xff09;&#xff1a…

【MIT 6.S081】2020, 实验记录(9),Lab: file system

目录 Task 1&#xff1a;Large filesTask 2&#xff1a;Symbolic links2.1 增加一个系统调用 symlink2.2 新增文件类型2.3 新增 NOFOLLOW 标志位2.4 实现 sys_symlink 系统调用2.5 修改 sys_open 函数2.6 测试 Task 1&#xff1a;Large files 现在的 xv6 系统中&#xff0c;一…

算法——贪心算法

《算法图解》——贪心算法 # 首先创建一个表&#xff0c;包含所覆盖的州 states_needed set([mt,wa,or,id,nv,ut,az]) # 传入一个数组&#xff0c;转换成一个集合#可供选择的广播台清单 stations {} stations[kone] set([id,nv,ut]) #用集合表示想要覆盖的州&#xff0c;且不…

EMQX 4.0和EMQX 5.0集群架构实现1亿MQTT连接哪些改进

EMQX 5.0水平扩展能力得到了指数级提升&#xff0c;能够更可靠地承载更大规模的物联网设备连接量。 在EMQX5.0正式发布前的性能测试中&#xff0c;我们通过一个23节点的EMQX集群&#xff0c;全球首个达成了1亿MQTT连接每秒100万消息吞吐&#xff0c;这也使得EMQX 5.0成为目前为…

Jenkins流水线将制品发布到Nexus存储库

1、安装jenkins&#xff08;建议别用docker安装&#xff0c;坑太多&#xff09; docker run -d -p 8089:8080 -p 10241:50000 -v /var/jenkins_workspace:/var/jenkins_home -v /etc/localtime:/etc/localtime --name my_jenkins --userroot jenkins/jenkins:2.449 坑1 打开x…

Python使用 k 均值对遥感图像进行语义分割

本篇文章介绍K-means语义分割来估计 2000 年至 2023 年咸海水面的变化 让我们先看一下本教程中将使用的数据。这是同一地区的两张 RGB 图像,间隔 23 年,但很明显地表特性和大气条件(云、气溶胶等)不同。这就是为什么我决定训练两个独立的 k-Means 模型,每个图像一个。 首…