C/C++中整数与浮点数在内存中的表示方式
在C/C++中数字类型主要有整数与浮点数两种类型,在32位机器中整型占4字节,浮点数分为float,double两种类型,其中float占4字节,而double占8字节。下面来说明它们在内存中的具体表现形式:
整型:
整型变量占4字节,在计算机中都是用二进制表示,整型有无符号和有符号两种形式。
无符号变量在定义时只需要在相应类型名前加上unsigned 无符号整型变量用32位的二进制数字表示,在与十进制进行转化时只需要知道计算规则即可轻松转化。需要注意的是在计算机中一般使用主机字节序,即采用“高高低低的方式”,数字高位在高地址位,低位在低地址位,例如我们有一个整数0x10203040那么它在内存中存储的格式为:04 03 02 01。
有符号数将最高位表示为符号位,0为正数,1为负数其余位都表示具体的数值,对于负数采用的是补码的方式,补码的规则是用0x100000000减去这个数的绝对值,也可以简单的几位将这个数的绝对值取反加1,这样做是为了方便将减法转化为加法,在数学中两个互为相反数的和为0,比如现在有一个负数数x,那么这个x + |x| = 0这个x的绝对值是一个正数,但是用二级制表示的两个数相加不会等于0,而计算机对于溢出采用的是简单的将溢出位丢弃,所以令x + |x| = 0x100000000,这个最高位1,已经溢出,所以这个结果用四字节保存结果肯定会是0,所以最终得到的x = 0x100000000 - |x|。
浮点数:
早期的小数表示采用的固定小数点的方式,比如规定在32位二级制数字当中,哪几位表示整数部分,其余的表示小数部分,这样表示的数据范围有限,后来采用的是小数点浮动变化的表示方式,也就是所谓的浮点数。
浮点数采用的是IEEE的表示方式,最高位表示符号位,在剩余的31位中,从左往右8位表示的是科学计数法的指数部分,其余的表示整数部分。例如我们将12.25f化为浮点数的表示方式:
首先将它化为二进制表示1100.01,利用科学计数法可以表述为:1.10001 * 2^3
分解出各个部分:指数部分3 + 127= 011 + 0111111、尾数数部分:10001
需要注意的是:因为用科学计数法来表示的话,最高位肯定为1所以这个1不会被表示出来
指数部分也有正负之分,最高位为1表示正指数,为0表示负指数,所以算出来指数部分后需要加上127进行转化。
将这个转化为对应的32位二级制,尾数部分从31位开始填写,不足部分补0即:0 | 10000010 | 10001 |000000000000000000,隔开的位置分别为符号位、指数位,尾数位。
因为有的浮点数没有办法完全化为二进制数,会产生一个无限值,编译器会舍弃一部分内容,也就说只能表示一个近似的数,所以在比较浮点数是否为0的时候不要用==而应该用近似表示,允许一定的误差,比如下面的代码:
float fTemp = 0.0001f
if(fFloat >= -fTemp && fFloat <= fTemp)
{
//这个是比较fFloat为0
}
double类型的浮点数的编码方式与float相同,只是位数不同。double用11位表示指数部分,其余的表示尾数部分。
浮点数的计算在CPU中有专门的浮点数寄存器,和对应的计算指令,在效率上比整型数据的低。
在写程序的时候,我们利用变量名来进行变量的识别,但是计算机根本不认识这些变量名,计算机中采用的是直接使用地址的方式找到对应的变量,同时为了能准确找到对应的变量,编译器会生成一个结构专门用于保存变量的标识名与对应的地址,这个标识名不是我们定义的变量名,而是在此基础上添加了一些符号,如下面的例子:
extern int nTemp;
int main()
{
cout<<nTemp<<endl;
}
我们申明一个变量,然后在不定义它的情况下,直接使用,这个时候编译器会报错,表示找不到这个变量,报错的截图如下:
我们可以看到编译器为这个变量准备的名称并不是我们所定义的nTemp,而是添加了其他标示。
在声明变量的时候编译器会为它准备一个标示名称,在定义时会给它一个对应的内存地址,以后在访问这个标示的时候编译器直接去它对应的内存位置去寻找它,下面我们添加这个变量的定义代码:
extern int nTemp;
int nTemp = ;
int main()
{
cout<<nTemp<<endl;
return ;
}
我们查看对应的汇编代码:
: ;int nTemp = ;
mov dword ptr [ebp-],
: ;cout<<nTemp<<endl;
我们可以看到在为这个变量初始化的时候编译器是直接找到对应的地址[ebp - 4],没有出现相关的变量名,所以说我们定义的变量名只是为了程序员能够识别,而计算机是直接采用寄存器寻址的方式来取用变量。
在编译器中同时也看不到与变量类型相关的代码,编译器在使用变量是只关心它的位置,存储的值,以及如何将其中的二进制翻译为对应的内容,代码如下:
int main()
{
int nTemp = 0x00010101;
float *pFloat = (float*)&nTemp;
char *pChar = (char*)&nTemp;
cout<<nTemp<<endl;
cout<<*pFloat<<endl;
cout<<pChar<<endl;
return ;
}
结果如下:
从这可以看出同一块内存因为编译器根据类型将它翻译为不同的内容,所展现的内容不同。
C/C++中整数与浮点数在内存中的表示方式的更多相关文章
- <转载>浅谈C/C++的浮点数在内存中的存储方式
C/C++浮点数在内存中的存储方式 任何数据在内存中都是以二进制的形式存储的,例如一个short型数据1156,其二进制表示形式为00000100 10000100.则在Intel CPU架构的系统中 ...
- vs中调试程序查看变量在内存中的内容的方法
vs中调试程序 查看变量在内存中的内容的方法 https://blog.csdn.net/guojg1988/article/details/42922149 原文链接:http://www.sows ...
- @清晰掉 C++ 中的 enum 结构在内存中是怎么存储的?
C++ 中的 enum 结构在内存中是怎么存储的? C++ C++ 中的 enum 结构在内存中是怎么存储的?里面存储的是常量值吗? 关于占用内存的大小,enum类型本身是不占内存的,编译器直接 ...
- Tomcat启动时加载数据到缓存---web.xml中listener加载顺序(例如顺序:1、初始化spring容器,2、初始化线程池,3、加载业务代码,将数据库中数据加载到内存中)
最近公司要做功能迁移,原来的后台使用的Netty,现在要迁移到在uap上,也就是说所有后台的代码不能通过netty写的加载顺序加载了. 问题就来了,怎样让迁移到tomcat的代码按照原来的加载顺序进行 ...
- Python中整数和浮点数
Python支持对整数和浮点数直接进行四则混合运算,运算规则和数学上的四则运算规则完全一致. 基本的运算: 1 + 2 + 3 # ==> 6 4 * 5 - 6 # ==> 14 7.5 ...
- c/c++浮点数在内存中存储方式
转自:https://www.cnblogs.com/dolphin0520/archive/2011/10/02/2198280.html 任何数据在内存中都是以二进制的形式存储的,例如一个shor ...
- C语言中浮点数在内存中的存储方式
关于多字节数据类型在内存中的存储问题 //////////////////////////////////////////////////////////////// int ,short 各自是4. ...
- java中的各种数据类型在内存中存储的方式
原文地址:http://blog.csdn.net/aaa1117a8w5s6d/article/details/8251456 1.Java是如何管理内存的 java的内存管理就是对象的分配和释放问 ...
- C/C++浮点数在内存中的存储方式
一.内存表示 任何数据在内存中都是以二进制的形式存储的,浮点数的表示是把一个数的有效数字和数的范围在计算机的一个存储单元中分别予以表示,数的小数点位置随比例因子的不同而在一定范围内自由浮动.如下图是3 ...
随机推荐
- js中的true,false盲点
上一篇博客提到了一个js的小问题,我当时的解释不太清晰,后面请教胡大大才弄明白js中的处理. js里面检查true和false的过程是这样的: 所以'0'在逻辑判断里面,是被当做true. if('0 ...
- Docker集群实验环境布署--swarm【1 架构说明】
在读完<Docker技术入门与实践>这本书后,基本上已对Docker了有一些入门的理解,以及我们为什么要使用Docker 答:我们发现在实际工作中,通过openstack一旦把一个VM创建 ...
- 《DSP using MATLAB》示例 Example 6.5
代码: b = [1, 0, 0, 0, 16+1/16, 0, 0, 0, 1]; broots = roots(b) B1 = real(poly([broots(1), broots(2), b ...
- MemoryStream和FileStream
一,FileStream对象的数据来自文件,而MemoryStream对象的数据来自内存缓冲区.这两个类都继承自Stream类. 二,抽象基类System.IO.Stream代表流,它提供Read和W ...
- Redis的安装和使用之------Redis相关运用
原文 http://wangzhijian.blog.51cto.com/6427016/1731962 一.简介 REmote DIctionary Server(Redis) 是一个由 Salv ...
- 【LeetCode】23. Merge k Sorted Lists
合并k个已合并链表. 思路:先把链表两两合并,直到合并至只有一个链表 /** * Definition for singly-linked list. * struct ListNode { * in ...
- python——爬虫
网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本.另外一些不常使用的名字还有蚂蚁.自动索引.模拟程序或者蠕 ...
- PNG文件转png8
png8比普通png图片会小很多,所以在开发中为了是图片加载速度更快我们可以把Png图片都转成png8 首先添加 ImageProcessor 包 private byte[] ConvertTo ...
- 如何运用xp_cmdshell 执行多行cmd命令
因为需要利用sql 脚本调用外部程序,所以尝试xp_cmdshell 命令,发现其默认只能执行一行命令,最后找到了下面方法: 将多行cmd 命令处理成bat文件,然后直接利用所在路径+文件来执行: ...
- eclipse 一些快捷键
快捷键 alt + 上下方向键 向后缩进 shift + tab 整体向左移动 tab 就是向右移动 ctrl + Q 就是构建有参的构造方法 ctrl + E 是get set 方法,要把quick ...