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的正数原码反码补码都是//00000000000000000000000000001001float* pFloat = (float*)&n;//0 00000000 00000000000000000001001printf("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 0010000000000000000000printf("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^3return 0;
}
总结:
我们在内存中如果以整数储存数据,但是用浮点数的方式来读取,用的是浮点数的读取规则。
我们在内存中如果以浮点数储存数据,但是用整数的方式来读取,用的是整数的读取规则。