在计算机中的数据又整数和小数之分,而它们的存储方式不同,所以我们一次来进行讨论
1.整数在内存中的存储
1.1
说到整数在内存中的存储,就不得不提原码,反码和补码.那么什么是原码,反码和补码呢?
计算机只能读懂0和1组成的二进制序列,所以也要将要存入的数用对应的二进制序列来表示
在C语言中整数默认为int类型,那么我们就以4个字节的int类型数据为例.
4个字节相当于32位,即32个bit位. 换言之,在内存中是由32个0/1的数组成的序列,而从右向左位数一次增加,最高位存的是符号位,0表示正数,1表示负数.
如图:
2和-2的原码出了符号位不同,其他一模一样.
而正数又和负数有所不同:正数的原码,反码,补码一样.而负数反码是符号位不变其他位按位取反,补码是反码+1.
如图:
而计算机中对于正数,所存的就是其补码.
1.2
什么是大小端?
看上图, i的值是0x11223344,但在内存中却是倒着存的,这是为什么?
在这里有一个大小端的概念.
小端存储:就是数据的低位字节序存放在高地址处,而数据的高位字节序存放在低地址处.
大端存储:数据的低位字节序存放在低地址处,数据的高位字节序存放在高地址处.
而究竟是大端存储还是小端存储,取决于硬件设备.
而在我这台机器中就是小端存储.
2.浮点数的存储
2.1 规则
首先要知道浮点数如何使用二进制数来表示
举个例子:浮点数 5.5 它表示为二进制数为: 101.1 为什么是这么存储的.
首先看小数点左边的:这个很好理解,因为5的二进制数就是101
那么小数点右边呢?
小数点右边其实也是一样的,小数点左边向左的权重依次是(2^0,2^1,.......2^n),而小数点右边的权重则是(2^-1, 2_-1, 2^3......)
而2^-1正好为0.5,所以5.5的二进制数为:101.1
所以我们可以将101.1改写一个形式:
(-1)^0 * 1.011* 2 ^ 2
根据以上公式: 5.5对应的 ( s = 0, M = 1.011, E = 2)
所以在存储中是将这几个数存到内存中的,但又没那么简单,我们下面来说明.
2.2 存储
浮点数分为double类型的和float类型的(double是64位,float是32位)
存储方式如图所示:
我们就以float类型的浮点数位例.
首先是最高位,和整数一样存储符号位,0表示正数,1表示负数. 所以只需要在最高位上存入1和0即可.
之后再看E: E有点小复杂.规定E为一个无符号整数, 简单来说就是非负数,但是这似乎是不合理的,因为总有那么些数,E是小于零的,那么怎么办呢? 所以我们需要找到中间数,float中间数为127,double的中间数为1023.什么意思呢,其实就是让我算出来的E再加上中间数 ,中间数一定符合条件,再将这个中间数的二进制序列存到内存中. 当然,有的朋友可能会说,如果加上中间数还是小于零该怎么办呢,这种情况太极端,我们不考虑极端情况,在现实生活中也没有什么意义.ok
最后看M:前面的公式中提到过,M的范围是(1<=M < 2).所以M一定是一个一点几的一个数.
所以我们可以我们可以不存这个1,只存会变化的后面的小数,这样可以多留一位存有效值.
而如果剩余空间没有存完,那么就在后面放0即可.
说完了,那么我们来看看前面的例子,5.5.
S = 0 M = 1.011, E = 2
s = 0 直接在最高位存0
E = 2 ,加上127 等于 129 对应的二进制序列为:10000001 存在后面8位
M = 1.011 只需要存011即可
剩下还有20位的空间全部补0
所以最终结果就是: 0 10000001 01100000000000000000000