首页 > C语言中整型浮点型在计算机中的存储

C语言中整型浮点型在计算机中的存储

   第一次写博客,遣词造句有点菜,算是一次简单梳理,慢慢学习人家的博客风格,随着学习的深入再做修改。

  本次学习的是C语言在VS下的编译调试,对于初学者两说,首先说一下如何监控变量,以及监控变量在内存中的存储与表示。

 1. 如何监控变量

  首先从最基本的程序说起,先看一段代码,

  

#includeint main()
{int i;for (i = 0; i <= 5; i++)printf("%d
",i);return 0;
}


  这样很简单的一段代码,我们想随时监控变量i的值的变换以及在内存的变化,应该如何去做的,首先VS中按F10进入调试状态,依次打开调试->窗口->监视->监视1,如下图所示





  在编辑窗口的下方会出现如下的对话框,在名称下面输入i,依次按F10就可以监控变量,这种方式在我们以后的编程查错时会很方便。



  2.如何查看变量在内存中的变化

  还是上面的简单程序,按F10进入调试状态,和上述步骤相似,依次打 调试->窗口->内存->内存1,然后出现如下窗口,窗口大小位置都可以进行修改,自己尝试。

  

此时我们只需要点击窗口中最下面的内存1和监视1,就可以对变量i的值和内存的监控的随意切换。但是我们还需要在上面的窗口的地址栏输入i的地址才可以进行监控,输入&i

,然后回车。此时地址栏显示的地址即为i在计算机的存储地址,然后依次按F10即可监控i对应的地址中值的变化



按几次F10之后,我们会看到i此时的值为1,下面是此时i的值的监视,和i在内存地址中的值

我们发现i此时值为1,那i在内存中的值是什么呢,看上面内存监视,第一行0x004FFEDC后面对应的八个数字,01 00 00 00 ,我们知道计算机的存储是二进制存储,但是二进制表示的话会很长,不利于观察和计算,于是编译器就把二进制数转化成十六进制表示出来,又计算机是小端模式(读者自行了解),所以将01 00 00 00的十六进制转化成十进制就是1.我们同样的方式再来看一下其他数值是否符合这个规则。稍改一下程序,让i的循环终止时候的值是20,如下图



需要解释的一点是,我刚刚把for循环括号里面i<=5,改成了i<=20,此时重新编译,所以地址改变,但是不影响对内存中值的监视,此时我们看到,当i的值为20时,对应地址中的值是14 00 00 00化成十进制就是20.大家可以按照这个方式,设计一些程序去检测一下。

3.浮点型在计算机中的存储

   在探讨float的存储呢之前可以先说一下整型在计算机内存中的存储是补码形式,大家可以自行试验一下,包括负数的存储呢形式,这里不再熬述。

  有了上述的基础之后,我们在讨论浮点型在计算机中是如何存储的。

  首先明白两个前提条件 (1)实型数据在计算机中以指数的形式保存

                                            (2)float在计算机中占四个字节,符号位1位,指数位8位,尾数位23位

  我们还是通过简单的例子看看计算机是如何存储的

#includeint main()
{float i;i = 0.5;return 0;
}




  

  我们看到当i的值为0.5时,其对应的二进制数是0.1,指数表示应该是1.0*2^-1内存中的值是00 00 00 3f,将它转换成大端存储为3f 00 00 00,再转化成二进制数为0011 1111 0000 0000 0000 0000 0000  0000,按照float数据的存储方式可以将其划分为1个符号位,8个指数位,和23个尾数位的形式,则其为0      01111110       00000000000000000000000

我们知道符号位没错是0,但是尾数为啥全部为零呢,这是因为,float存储时,不论怎么做,小数点后面总会出现一个1,这样计算机就默认一个1.这样就可以提高一个位的精度。在解决了这个问题以后,我们又要问了,那指数位也不符合我们的要求啊。我们把指数位的数转化成十进制数为01111110(二进制)->126(十进制)

这是怎么回事呢,指数不是应该是-1吗,这和我们的126有什么关系吗,不难发现126=127+(-1)

根据以上分析我们得到计算机存储float的两个推断(1)尾数部分处理成了1.xxx * 2^n的形式

                                                                                        (2)指数部分在原有的基础之上加127

下面来举例验证一下我们的推论是否正确比如0.25,转化成二进制就是0.01,根据我们的推论,将其转换成指数形式就是1.0 * 2^(-2),那么尾数位还全部是0,则指数位应该是-2+127=125,125的二进制表示应该是0111 1101,那么0.25(十进制)在内存中的表示应该是0   01111101   00000000000000000000000  我们来通过程序验证一下,

0.25在内存中的表示为00 00 80 3e,将其装换成小端模式为3e 80 00 00,再将其转化成二进制为  0        01111101     00000000000000000000000,和上述我们的推断一致,证明推断正确。此时又会问了为什么会采用这种方式进行存储呢?如果直接按照指数的存储形式,采用补码的话,我们必须要思考两个数字0.0和1.0如何存储,0.0毋庸置疑是全0,可是1.0按普通补码的形式,应该是1.0*2^0指数部分也应该是全0,但是这样不就和0.0矛盾了吗,所以需要才要指数加127的操作。接下来我们验证一下0.0和1.0在计算机内存中是如何存储的。

0.0



0.0是全0



1.0



1.0是00 00 80 3f转化成小端是3f 80 00 00再转化成二进制是0     01111111      00000000000000000000000再将指数位转化成十进制是127.此时可以说我们的结论正确了。

  综上,float在计算机内存中采取以下方式进行存储

             1. 尾数部分处理成了 1.xxxx * 2^n的格式

             2. 指数部分在原有指数的基础上加了 127





以上文字仅是个人拙见,错误之处,还望大家指正,本人也会深入学习,争取在文字表达还有正确性上面更精准一些。

更多相关:

  • 英语的重要性,毋庸置疑!尤其对广大职场人士,掌握英语意味着就多了一项竞争的技能。那,对于我们成人来说,时间是最宝贵的。如何短时间内在英语方面有所突破,这是我们最关心的事情。英语学习,到底有没有捷径可以走,是否可以速成?周老师在这里明确告诉大家,英语学习,没有绝对的捷径走,但是可以少走弯路。十多年的教学经验告诉我们,成功的学习方法可以借...

  • 展开全部 其实IDLE提供了一个显32313133353236313431303231363533e78988e69d8331333365663438示所有行和所有字符的功能。 我们打开IDLE shell或者IDLE编辑器,可以看到左下角有个Ln和Col,事实上,Ln是当前光标所在行,Col是当前光标所在列。 我们如果想得到文件代码...

  • 前言[1]从 Main 方法说起[2]走进 Tomcat 内部[3]总结[4]《Java 2019 超神之路》《Dubbo 实现原理与源码解析 —— 精品合集》《Spring 实现原理与源码解析 —— 精品合集》《MyBatis 实现原理与源码解析 —— 精品合集》《Spring MVC 实现原理与源码解析 —— 精品合集》《Spri...

  • 【本文摘要】【注】本文所述内容为学习Yjango《学习观》相关视频之后的总结,观点归Yjango所有,本文仅作为学习之用。阅读本节,会让你对英语这类运动类知识的学习豁然开朗,你会知道英语学习方面,我们的症结所在。学习英语这类运动类知识,需要把握四个原则第一,不要用主动意识。第二,关注于端对端第三,输入输出符合实际情况第四,通过多个例子...

  • 点云PCL免费知识星球,点云论文速读。文章:RGB-D SLAM with Structural Regularities作者:Yanyan Li , Raza Yunus , Nikolas Brasch , Nassir Navab and Federico Tombari编译:点云PCL代码:https://github.co...

  • Bigtable 可以说是log-structed以及page-oriented 两种存储引擎的整合体,我们性能优越的单机存储引擎leveldb和rocksdb就是基于google的bigtable存储系统实现的。 论文地址Bigtable: A Distributed Storage System for Structured Da...

  • 一下为个人结合其他人对分布式存储 所需的技能进行总结,绘制成如下图谱,方便针对性学习。 这里对分布式存储系统接触较多的是ceph,所以在分布式存储系统分支上偏向ceph的学习。 如有分类有问题或者分支不合理,欢迎大家批评指正,目的是为了大家共同提升 文章目录分布式存储技能树Linux操作系统文件系统I/O系统I/O追踪内存管理Pag...

  • 存储过程存储过程分为系统存储过程和自定义存储过程存储过程通过将处理数据的程序从客户端应用程序移动到服务器,存储过程是放在服务器上的,通过客户端下达指令调用存储过程的时候,这个过程是在服务器上发生的,自然就不会占用网络的带宽就会降低网络流量。存储过程就是一组为了完成特定功能的T-SQL语句...

  • 原文地址:https://github.com/jaywcjlove/handbook/blob/master/MySQL/MySQL%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B.md MySQL数据类型 数字类型 整数: tinyint、smallint、mediumint、int、bigint浮点数:...

  • 为什么要用存储过程   几个去 IBM 面试的兄弟回来抱怨:去了好几个不同的 IBM 项目组,几乎每个面试官问到数据库的时候都要问用没用过存储过程,烦人不?大家去面的程序员,又不是 DBA,以前的项目都没有用到存储,不照样运行的好好的? 存储过程真的那么重要吗,它到底有什么好处呢? 笔者认为,存储过程说白了就是一堆 SQL 的合并。...

  • 更多内容,欢迎关注微信公众号:全菜工程师小辉~前言在笔者上一篇博客,详解了NIO,并总结NIO相比BIO的效率要高的三个原因,彻底搞懂NIO效率高的原理。这篇博客将针对第三个原因,进行更详细的讲解。首先澄清,零拷贝与内存直接映射并不是Java中独有的概念,并且这两个技术并不是等价的。零拷贝零拷贝是指避免在用户态(User-space)...

  • 一、预备知识—程序的内存分配  一个由c/C++编译的程序占用的内存分为以下几个部分  1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈,如果还不清楚,那么就把它想成数组,它的内存分配是连续分配的,即,所分配的内存是在一块连续的内存区域内.当我们声明变量时,那么编译器...

  • 我的爱机是一台ThinkPad T420,原装三星DDR 1333 4G内存一根,还剩一根内存位置,最近趁京东6.18促销,准备增加一根物理内存。为了确保兼容性,觉得仍然选购DDR 1333 4G内存,于是购买了金士顿这款,比如DDR3 1600的还贵。 这个安装过程完全参照该内存的网页提示进行 这里简单记录一下,以备...

  • 陪伴我多年的老本ThinkPad T420渐渐垂垂老矣, 我想更新一下可以更新的部分, 比如将2.5寸HDD更换为SSD, 将单条4G内存再增加一根, 凡此种种想法, 可能最后归结为如何获取该笔记本的硬件配置信息, 在windows下面使用鲁大师之类的检测软件, 也许很好搞定,但是在Ubuntu 14.04平台上如果办到呢? 很简单...

  • 一.内存错误出现的场景 这几天在重构ATS插件代码的过程中遇到了烦人的内存泄露问题, 周五周六连续两天通过走查代码的方法,未能看出明显的导致内存错误的代码, 同时也觉得C和C++混合编程得到一个动态库, 在一个.cpp主文件中,即用new又用malloc来动态分配内存, 可能会导致内存错误.后来网上调研和查资料发现, new和mal...