数据的存储(进阶)
1. 数据的类型
数据的类型决定了看待数据的方式,也就是存(开辟空间的大小)和取(连续读取几个字节)。
2. 计算机存储数据的方式
a:计算机存储数据都是补码;
原码:一个数字的二进制序列,负数:(+符号位);
反码:原码符号位不变,其他位按位取反;
补码:反码+1;
b:对于补码:
无符号数或者正数,原反补相等;
有符号负数,原反补转化;
c:计算机存储的方式:
存:原码->补码;
取:补码->原码;
3. 什么是大端小端
大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;
小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,,保存在内存的高地址中。
判断的代码:
#include <stdio.h>
int check_sys()
{
int i = 1;
return (*(char *)&i);//强转为char *,读取发生截断,只能读一字节;输出为1为小端,输出0为大端;
}
int main()
{
int ret = check_sys();
if(ret == 1)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
4. 浮点数的存储
首先看一段代码:
int main()
{
int n = 9;
float *pFloat = (float *)&n;
printf("n的值为:%d\n",n);//输出为9
printf("*pFloat的值为:%f\n",*pFloat);//输出为0
*pFloat = 9.0;
printf("num的值为:%d\n",n);//输出为1091567616
printf("*pFloat的值为:%f\n",*pFloat);//输出为9.0
return 0;
}
a:一个二进制浮点数V可以表示成下面的形式:
(-1)^S * M * 2^E
(-1)^s表示符号位,当s=0,V为正数;当s=1,V为负数。
M表示有效数字,大于等于1,小于2。
2^E表示指数位
b:存储模型
float的存储模型:
s(1比特位)E(8比特位)M(23比特位)
double的存储模型:
s(1比特位)E(11比特位)M(52比特位)
c:标准科学计数法M一定是个1.xxx,存储的时候只存xxx(取的时候自动加上1. ),从左向右依次排放,多余位置填补0;
E为一个无符号整数(unsigned int) 这意味着,如果E为8位,它的取值范围为0~255;
如果E为11位,它的取值范围为0~2047。但是,我们知道,科学计数法中的E是可以出现负数的,所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。
d:转换过程:
存:
1. 转换成为二进制;
2. 转化为标准科学计数法;
3. 提取S、M、E;
4. 存放S、M、E;
取:
1. 取S、M、E;
2. 带入标准科学计数法;
3. 转化成二进制;
4. 二进制转化为数据;
e:特殊情况:(M不左右浮点数的大小,其大小由E决定)
对于一个数:(-1)^S * M * 2^E(-127)
如果s=0,则这个浮点数自右向左无限趋近于0;如果s=-1,其为无限趋近于0的负数,这两中情况就构成了一个区间;
(规定1000 0000为128)
所以就有以下情况:
1. E为0000 0000:这时,浮点数的指数E等于1-127(或者1-1023)即为真实值, 有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字
2. E为1111 1111 :这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);
3. E不全为0或者不全为1:符合规则。