1. 整数在内存中的存储
2. ⼤⼩端字节序和字节序判断
3. 浮点数在内存中的存储
我本将心向明月,奈何明月照沟渠
正文开始
一、.整数在内存中的储存
整数的2进制的表示方法有三种
1.原码
2.反码
3.补码
这里在第十章我们有详细讲解,有需要的同学可以自行观看。
二、大小端字节序和字节序判断
int main()
{
int a = 0x11223344;
return 0;
}
2.1 什么是大小端字节序储存呢?
我们来用图形来表示一下
小端字节序: 是数据的低字节内容保存在低地址处,数据的高字节内容保存在高地址处
大端字节序:是数据的低字节内容保存在高地址处,
数据的高字节内容保存在低地址处
int check_system(void)
{
int i = 1;
return (*(char*)&i); // 这里我们来强制类型转换是为了判断它的起始收字符是不是为1
//,如果是1就是小端,否则就大端
}
int main()
{
int ret = check_system();
if (1 == ret)
{
printf("小端");
}
else
{
printf("大端");
}
return 0;
}
我们该计算机系统用的是小端字节序
三、浮点数在内存中的存储
常见的浮点数:3.14159 、1E10 等,浮点数的家族包括 float,double,long double 类型
这里我们先引入一个练习
#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;
}
3.2 浮点数的存储
通过上面我们可以看出,n 和*pFloat 在明明是一个数,为什么浮点数和整数的解读结果会差别很大呢?
我们可以猜测一下,难道是因为浮点数和整数的储存方式是不一样的吗?
接下来我们来分析浮点数在内存中的储存方式
根据国际标准IEEE(电⽓和电⼦⼯程协会) 754,任意⼀个⼆进制浮点数V可以表⽰成下⾯的形式:
V = (−1) ∗ S M ∗
• (−1)S 表⽰符号位,当S=0,V为正数;当S=1,V为负数
• M 表⽰有效数字,M是⼤于等于1,⼩于2的
•
表示的是指数位
举例来说:十进制的5.0,写成二进制是101.0,相当于1.01 * 2^2
那么我们按照上边的关系就可以得出
- S = 0
- M=1.01
- E = 2
IEEE规定:
对于32位的浮点数,最高的1位储存符号位 S ,接着8位储存指数E,剩下的32位储存有效数字M
对于64位的浮点数,最高的1位储存符号位 S ,接着11位储存指数E,剩下的52位储存有效数字M
3.2.1 浮点数储存的一些特点
对于有效数字M和指数E
还有一些特殊的规定:
1.
前⾯说过, 1≤M<2 ,也就是说,M可以写成 1.xxxxxx 的形式,其中 xxxxxx 表⽰⼩数部分。在计算机内部保存M时,默认这个数的第⼀位总是1,因此可以被舍去,只保存后⾯的xxxxxx部分。⽐如保存1.01的时候,只保存01,等到读取的时候,再把第⼀位的1加上去。这样做的⽬的,是节省1位有效数字。以32位浮点数为例,留给M只有23位,将第⼀位的1舍去以后,等于可以保存24位有效数字。
首先我们要知道的是E为一个无符号整数
但是科学计数法E是可以出现负数的,所以规定就说
存⼊内存时E的真实值必须再加上⼀个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数1023。⽐如,2^10的E是10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001。
3.2.2
浮点数取得过程
指数E从内存中取出还可以分为以下三种情况
1.E不全为0或不全为1(正常取)
这时,浮点数就采⽤下⾯的规则表⽰,即指数E的计算值减去127(或1023),得到真实值,再将有效
数字M前加上第⼀位的1。
2.E全为0
这时,浮点数的指数E等于1-127(或者1-1023)即为真实值,有效数字M不再加上第⼀位的1,⽽是还
原为0.xxxxxx的⼩数。这样做是为了表⽰±0,以及接近于0的很⼩的数字。
3.E全为1
这时,如果有效数字M全为0,表⽰±⽆穷⼤(正负取决于符号位s);
这里我们就可以重新的分析上边的那个例子
#include <stdio.h>
int main()
{
int n = 9;
//9的正数原码反码补码都是
//00000000000000000000000000001001
float* pFloat = (float*)&n;
//0 00000000 00000000000000000001001
printf("n的值为:%d\n", n);
printf("*pFloat的值为:%f\n", *pFloat);
// S = 0 ,E = 1-127 , M = 00000000000000000001001
// V = (-1)^0 × 0.00000000000000000001001×2^(-126)=1.001×2^(-146) 约等于0
*pFloat = 9.0;
//9.0的二进制为1001.0 = 1.001 * 2^3
//9.0在内存中的储存为
//0 10000010 0010000000000000000000
printf("num的值为:%d\n", n);
// 按照 十进制的读取方式就为
//0100000100010000000000000000000 ==1091567616
//0 为正整数原码反码补码相同
printf("*pFloat的值为:%f\n", *pFloat);
//0 10000010 0010000000000000000000
//我们还原 就可得到
//S = 0
//M = 1.001
//E = 130-127 = 3
//V = (-1)^0 * 1.001 * 2^3
return 0;
}
总结:
我们在内存中如果以整数储存数据,但是用浮点数的方式来读取,用的是浮点数的读取规则。
我们在内存中如果以浮点数储存数据,但是用整数的方式来读取,用的是整数的读取规则。