一、整数在内存中存储
C语言中整数是整型int类型的数据,占用4个字节,因此需要4个存储单元来储存一个整型数据,这四个内存单元各存储这个int类型数据的部分数据,组合起来就会形成一个完整的int类型数据。而计算机中,每个内存单元都有自己独特的地址,从低到高依次排列。
假设一个int类型整数,用十六进制表示为0x11223344,显然11、22、33、44他们各自占一个字节,11是这个整数的高位,44是这个整数的低位,用十进制的“个十百千万”来类比理解,“万”是高位,“个”是低位。
计算机中数据的存储顺序最常见的有两种,一是数据的低位存储到内存低地址,高位存储到内存的高地址,称为小端存储方式;二是数据的低位存储到内存高地址,高位存储到内存的低地址,称为小端存储方式。
接下来测试我自己电脑的数据存储方式。
输出结果为小端,其原理如下:
只需要判断数据的低地址的数值是00还是01就能判断出计算机是小端存储还是大端存储。取a的地址&a,它的类型是int*,它指向4个字节,如果只想提取第一个低地址字节里的内容,需要转换&a的类型为char*,这样在解引用后*a的只会访问一个字节。
之后是判断:
查看内存进行确认:
低位的01确实被存储到了低地址上。
二、浮点数在内存中存储
浮点数在内存中的存储与整型不一样,浮点数的存储是按照IEEE754标准,存储了S、M、E相关的值(下面解释)。任何一个浮点数可以写作:
S是-1的s次方,s=0时,-1的0次方是正数,s=1时,-1的1次方是负数,C语言规定M是一个大于1小于2的数(1<M<2),E则是2的指数。
float类型浮点数占用4个字节,double类型占用8个字节。它们的内存字节分配如下图:
二进制数字每一位的权重是2的倍数,例如2进制浮点数101.111:
101.111代表的浮点数转化为十进制是5.875
5.875的二进制表示办法为101.111,它的S是0(代表正数),M是1.0111,E是2,因为:
所以它在内存中的存储为:
但在实际存储中,E的部分存入的不是2,M部分存入的也不是1.01111
首先解释M的存储:
因为M是一个大于1小于2的数据,不管是什么浮点数,转化为计算机的存储方式后,M的小数点左边一定是1,所以在存储m时,省略掉小数点左边的1,只存储小数点后面的数据。因此M虽然占用的只有23个字节,却能存储一个占用24个字节的M(相当于扩大了存储数据的精确范围,多存一位小数字节)。其在内存中存储方式如下图(省略掉小数点前的1,只存小数点后):
接下来解释E的存储:
E有可能取到负数,例如浮点数0.375,它的二进制写法为0.011:
它的M为1.1,E=-2:
而计算机存负数比存正数规则复杂,所以为了让计算机存储更加方便,在存储E的时候会给E加上一个中间量,float类型中间值127(8字节),double类型中间值1023(11字节),加上这个中间值后E恒为正数。
如果E=-2,那么在计算机内存中E=-2+127=125,当E=2时候,在计算机内存中存的值是E=129,所以101.111在内存中存储情况如下图:
将上图中的32字节的数据转化为16进制是:
又因为本计算机是小端存储方式,所以低位存入低地址,高位存入高地址,猜测其在内存中其实存储方式是:
在VS2022上进行验证:
查看内存:
在地址0x0039F774存储的的确是00 00 bc 40
以上是整型和浮点型数据在内存中的存储方式。