在说明数据在内存的存储前,先给大家介绍下大小端。
那么什么是大小端呢?
其实超过一个字节的数据在内存中存储的时候,就有存储顺序的问题,按照不同的存储顺序,我们分
为大端字节序存储和小端字节序存储,下面是具体的概念:
大端(存储)模式:是指数据的低位字节内容保存在内存的高地址处,而数据的高位字节内容,保存
在内存的低地址处。
小端(存储)模式:是指数据的低位字节内容保存在内存的低地址处,而数据的高位字节内容,保存
在内存的高地址处。
下面以图片进行更直观的描述
在搞懂什么是大小端之后。我们来思考一下为什么会有大小端呢?
这是因为在计算机系统中,存储是以字节为单位的,每个地址单元都对应一个字节,一个字节为8bit。在C语言中char 8bit,short 16bit,long 32bit(编译器不同会不同),所以必然存在一个如何将多字节安排的问题,这就导致了大端存储模式和小端存储模式。
int judge()//判断当前环境下是大端字节序还是小端字节序
{
int a = 1;
return *(char*)&a;
}
int main()
{
if (judge() == 1)
printf("小端");
else
printf("大端");
return 0;
}
我们知道整数的二进制表示方法有三种:原码,反码,补码
三种表示方法均有符号位和数值位(针对有符号数),最高位为‘0’表示‘正’,为‘1’表示‘负’,其余为数值位。
正整数原码,反码,补码相同。
负整数:
原码:将数值按照正负数的形式编译成二进制;
反码:将原码除符号位的其他位取反得到;
补码:反码+1得到
在数据存储在计算机里的就是补码
在明白大小端和整数在内存中的存储后,我们来看看下面一段代码
int main()
{
char a = -1;
signed char b = -1;
unsigned char c = -1;
printf("%d %d %d", a, b, c);}
这里的结果是-1,-1, 255。
由前面讲过的整数在内存中的存储,可以先把-1转化成三码
原码:10000000000000000000000000000001
反码: 1111111111111111111111111111111111110
补码:1111111111111111111111111111111111111
但是因为char的字节是8bit,所以只能把补码的候8位存入a,b,c。(11111111)
这里会涉及到一个整形提升的概念:
1.有符号整数提升是按照变量的数据类型的符号位来决定的
2.无符号整数提升,高位补0
所以可以知道 a和 b(有符号)中存入11111111111111111111111111111111(补码)->
10000000000000000000000000000000(反码)->1000000000000000000000000001(原码)
所以可以知道以%d形式输出a和b是-1
c(无符号)中存入00000000000000000000000011111111(补码)(反码)(原码),则c输出255
举一个浮点数例子5.5。表示除它的二进制数,我们知道整数二进制从右到左权重分别是2^0,2^1,2^2……可以推出小数点右边权重从左到右权重依次为2^-1,2^-2……所以5.5可以表示成101.1。那么如果是-5.5该如何表示呢?
根据国际标准IEEE754,任意一个二进制浮点数V可以表示成下面的形式:
V=(-1)^s * M *2^E
(-1)^s表示符号位,s=0为正,s=1为负
M表示有效数字,范围是(1,2)
2^E表示指数位
也就是说5.5可以写成1.011*2^2(s=0,M=1.011,E=2),-5.5写成-1.011*2^2。
IEEE754规定
对于32位的浮点数,第一位是S,接下来八位是M,剩下的是E
64位浮点数同理如图所示
但是并不是所有的浮点数都能精确的用二进制表示的如5.14,这就存在浮点数精度缺失问题,具体介绍看我之前写的《浮点数计算精度问题》
前面说M范围是(1,2),可以写成1.XXXX存储在23位中(32位浮点数),所以为了更精确,常常会把1给舍去,将XXXX存入,这样就精确了一位。
对于指数E(无符号整数)
E的范围是0~255,但是实际上是存在负数指数的,所以IEEE754 规定E存入内存时必须加上一个中间值,8位E加127,11位加1023
了解了浮点数的存储后,我们来讲讲浮点数的取数过程
1.E不全为0并且不全为1
E的计算值减去127得到真实值,有效数字M前补上1
比如0.5 1.0*2^-1,所以M为1.0补上舍去的1变为0,用23位补齐,E为-1,+127变为126(01111110),因为是整数所以s为0.所以0.5的二进制表示为
0 01111110 000000000000000000000
2.E全为0
真实值等于1-127=-126。一个数1.XXX乘以2^-126非常小,是一个接近于0的数。
3.E全为1
这是如果M全为0,则这个数表示为一个正负无穷大的数