一.整数在内存中的存储
首先,在讲解操作符的时候,我们就已经知道了,对于整形来说:数据存放内存中其实存放的是补码。并且我们也知道补码是整数的2进制表示方法之一。
整数的2进制表示方法有三种,即 原码、反码和补码
有符号的整数,三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,最高位的一位是被当做符号位,剩余的都是数值位。
正整数的原、反、补码都相同。 负整数的三种表示方法各不相同。
原码:直接将数值按照正负数的形式翻译成二进制得到的就是原码。
反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。
补码:反码+1就得到补码。
注:补码取反,再+1可得到原码。
但为什么存放的示补码,而不是原码呢 ?
这是因为在计算机系统中,数值一律用补码来表示和存储。 原因在于,使用补码,可以将符号位和数值域统⼀处理; 同时,加法和减法也可以统⼀处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是 相同的,不需要额外的硬件电路。
二.大小端字节序和字节序判断
首先我们先看下,下面的代码,我们发现再vs调试下a的数字是以字节为单位倒着存放的,这是因为字节的数据在内存中存储的时候,按照不同的存储顺序,我们分为大端字节序存储和小端字节序存储,而在vs中我们是以小端字节序存储。
1.什么是大小端字节存储?
当然在我们了解之前,我们还要知道什么是高位字节和地位字节。
一般来说字节的高低就是左边的为高字节右边的为低字节
例如 0x11223344 其中 11为高字节,44为低字节。
在二进制中11100010 00000000 11110000 11111000 其中11100010为高字节,11111000为低字节。
大端字节序存储: 是指数据的低位字节内容保存在内存的高地址处,而数据的高位字节内容,保存在内存的低地址处。
小端字节序存储: 是指数据的低位字节内容保存在内存的低地址处,而数据的高位字节内容,保存在内存的高地址处。
2. 判断为大端还是小端
#include <stdio.h>
int check_sys()
{
int a = 1;
if (*(char*)&a == 1)
return 1;
else
return 0;
}
int main()
{
if (check_sys()== 1)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
3.计算a的长度
#include <stdio.h>
int main()
{
char a[1000];
int i;
for (i = 0; i < 1000; i++)
{
a[i] = -1 - i;
}
printf("%d", strlen(a));
return 0;
}
我们知道字符的大小为一个字节,在二进制中一个字节为8bit所以字节的大小是从00000000到11111111,对于有符号的char来说,他的范围是-128~127,所以我们得出来的结果应为255.
三.浮点数在内存中的存储
1.浮点数的存储
根据国际标准IEEE,任意⼀个二进制浮点数V可以表示成下面的形式:
V =(−1)^S∗ M ∗ 2^E
S 表示符号位,当S=0,V为正数;当S=1,V为负数
• M 表示有效数字,M是大于等于1,小于2的
• 2 E 表示指数位
⼗进制的5.5 ,写成二进制是101.1
1 0 1 . 1
| | | |
2^2 2^1 2^0 2^-1
相当于1.011*2^2
其中S=0, M=1.011 ,E=2.
IEEE 754规定:
对于32位的浮点数,最⾼的1位存储符号位S,接着的8位存储指数E,剩下的23位存储有效数字M
对于64位的浮点数,最⾼的1位存储符号位S,接着的11位存储指数E,剩下的52位存储有效数字M
其中M是一个大于1小于2的数 ,也就是说,M可以写成 1.xxxxxx 的形式,其中 xxxxxx 表示小数部分。
对于指数E,它其实是一个无符号整数,如果E为8位,它的取值范围为0~255,如果E为11位,它的取值范围为0~2047,但是,我们知道,科学计数法中的E是可以出现负数的,所以为了防止这种情况,所以IEEE 754规定,存入内存时E的真实值必须再加上 一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。所以当我们保存浮点数的时候,我们要让E加上127或1023之后再转换成二进制的形式存储。
当然,既然我们存储了浮点数,之后我们肯定需要取出浮点数,进行计算,那么我们该如何取出浮点数呢?
2.浮点数取的过程
既然,我们存储浮点数的时候需要改变E的值,那么我们要取出浮点数的时候,也一定要改变E的值即让E-127或-1023。
这时,浮点数就采用下面的规则表示,即指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第⼀位的1。
然而指数E从内存中取出可以分成三种情况:
(1) E不全为0或不全为1
例如5.5的二进制是101.1可以写成1.011*2*2
可以得到S=0,M=1.011,E=2
32位下E=2+127=129
0 10000001 01100000000000000000000
可得到数值为1085276160
(2)E全为0
这时,浮点数的指数E等于1-127(或者1-1023)即为真实值,有效数字M不再加上第⼀位的1,⽽是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。
0 00000000 00100000000000000000000
这是E加完之后的二进制形式,发现E的二进制形式全为0,那么E=1-128(或者1-1023),得到才是原来的E=-127或-1022,然而2的-128次幂是一个分母很大的数,所以我们最后得到的数值就会变得趋于零
所以最后的值是接近于0的很小的数字
(3)E全为1
这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);
0 11111111 00010000000000000000000
当然这还是E加完之后的二进制形式,而8位二进制全为1的数值位255,那么255-127=128,而2的128次幂是一个很大的数,所以当E全为1时代表这无穷的数,而符合由S的值来决定。
好了,今天我们就讲的到这里吧,我们下一篇见!
标签:存储,字节,二进制,浮点数,补码,C语言,内存 From: https://blog.csdn.net/zm3rttqs9f/article/details/142137697