提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
提示:这里可以添加本文要记录的大概内容:
很多人往往认为整形和浮点数在内存中的存储是相同的,其实结果正好相反,整形和浮点数在内存中的存储规则并不同,而且浮点数的存储规则更多。下面我就以简单的方式教大家快速理解整形及浮点数的存储。
提示:以下是本篇文章正文内容,下面案例可供参考
一、整形及浮点数的大致介绍
整形分为有符号整形和无符号整形:
char : unsigned char signed char
int : unsigned int signed int
long : unsigned long signed long
大多数情况下编译器默认char int long等为有符号类型。计算机中的整数有三种二进制表示方法,分别是原码,反码,补码,而在内存中存储的便是补码,在进行运算的时候也是用补码进行计算。三种表示方法均是最高位为符号位,剩余为数值位。比如
为什么计算机中用补码存储呢?原因是使用补码可以将符号位和数值域统一处理,并且加法和减法也可以统一处理,在这声明一下cpu只有加法器,此外原码和补码相互转换,其运算过程是相同的,不需要额外的硬件电路。比如int c = 1-1在用补码计算时其实是int c = 1+(-1),在原反补的相互转化过程中,补码到原码可以有两种方法。
第一种:补码-1得到反码,然后反码符号位不变其他按位取反得到原码
第二种:补码符号位不变其他按位取反得到反码,反码+1得到原码。
同时刚刚在上图可以发现将-10的补码转化为16进制是ff ff ff f6,而在内存中是f6 ff ff ff,为什么会反呢?原因是各种编译器在取内存中数据的时候并不相同,有的从大的开始有的从小的开始,这就引入了大小端模式:
小端模式:将低位字节放到高地址。什么是低字节呢?如一百二十三这个整数,1是百位是高位,三是个位是低位。例:0x11223344 11是高位 44是低位。假设地址左边为低地址,右边为高地址:
将低位放入低地址为小端模式 , 相反将低位放入高地址为大端模式。这也就解释了刚刚看-10的内存为何相反,原因是我的编译器用的是小端存储。
那么如何判断自己的编译器用的是大端还是小端呢?以下给出两个方案:
#include <stdio.h>
int Judge()
{
int a = 1;
return *(char*)&a;
}
int main()
{
int ret = Judge();
if (ret==1)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
#include <stdio.h>
int main()
{
int a = 1;
char*p = (char*)&a;
if (*p==1)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
}
2.浮点数的介绍。
根据国际标准IEEE(电气和电子工程协会)754,任意一个二进制浮点数可以表示成以下形式:
(-1)^S*M*2^E s表示符号位,当s为0数为正,s为1是负数。
M表示有效数字,大于等于1,小于等于2.
2^E表示指数位
IEEE754规定,对于32位的浮点数,最高的1位为符号位s,接着的8位是指数E,剩下的23位为有效数字M。如图所示:
IEEE754规定,对于64位的浮点数,最高的1位为符号位s,接着的11位是指数E,剩下的52位为有效数字M。如图所示:
前面说过,M>=1&&M<2,那么M可以写成1.****的形式,IEEE754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存小数点后面的数,等到读的时候,再把刚刚舍去的1加上去,这样做的目的是节省一位有效数字来使小数点后面的精度更高。
举个例子:
至于指数E,IEEE754规定存入内存时E的真实值必须再加1个中间数,对于8位的E,这个中间值为127,对于11位的E,这个中间值为1023。比如,2^10中E为10,那么在保存32位浮点数时再加上127结果为137,即1001001.然而,指数E从内存中取出又分为三种情况:
第一种:E不全为0或不全为1
指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1。比如0.5的二进制为0.1,由于规定正数部分必须为1,所以将小数点向右移1位,变成1*2^(-1),E为(-1)+127==126,表示为011111110 二进制表示:0 01111110 00000000000000000000000
第二种:E全为0
指数E等于1-127(或-1023)得到真实值
第三种:E全为1
这时有效数字M全为0,表示正负无穷大,正负看符号位。
二、例题讲解
1.整形例题
代码如下(示例):
%u打印无符号整形,认为内存中存放的补码对应的是一个无符号数。
%d打印有符号整形,认为内存中存放的补码对应的是一个有符号数。
2.浮点数例题
代码如下(示例):