c语言中数据在内存中都是以二进制储存的,但是不同的数据类型储存的方式也不一样,我们先简单了解一下整数和浮点数在内存中储存的方式。
1.整数在内存中的存储
整数的二进制有三种表示方法:原码,反码,补码。一般在内存中存的是补码,
正数的原码,反码,补码都相同,
而负数的原码最高位是符号位,0表示正,1表示负,其他位用二进制来表示,
反码是原码的符号位不变,其他位取反+1,得到反码,
补码就是反码+1,
例如:-12
原码:10000000 00000000 00000000 00001100
反码:11111111 11111111 11111111 11110011
补码:11111111 11111111 11111111 11110100
2. 大小端字节序和字节序判断
了解了整数在内存中存储的方式,我们来看一道题,
# include <stdio.h> int main () { int a = 0x11223344 ; char* p=&a; *p = 0; printf("%x ", a); return 0 ; }
a会变成什么呢?
为什么改变的时44呢?这就涉及到大小端字节序的储存方式了,
⼤端(存储)模式:是指数据的 低位字节 内容保存在内存的⾼地址处,⽽数据的⾼位字节内容,保存 在内存的低地址处。
⼩端(存储)模式:是指数据的低位字节内容保存在内存的低地址处,⽽数据的⾼位字节内容,保存 在内存的⾼地址处。
低位字节和高位字节指的是权重,例如:
权重低的成称为低位字节,权重高的称为高位字节,
如何判断该字节序是大端储存还是小端储存呢?
int main() { int a = 0x11223344; char* p = &a; *p = 0; if (*((char*)&a) == 0) printf("小端\n"); else printf("大端\n"); return 0; }
3.浮点数在内存中的储存
浮点存的过程
知道整数的储存方式后,那么浮点数是怎么储存的呢?
例如:
十进制的 5.0 写成二进制是 101.0 ,也就是 1.01*2^2 (1<=M<2)
按上面的格式写就是:S=0,M=1.10,E=2 V=(-1)^0 * 1.01 * 2^2
内存中只储存S,M的小数部分,E
因为我们默认为M的整数部分为1,所以不去储存它,节省一位用来储存小数部分,使浮点数储存更精确。
IEEE 754规定:
对于32位的浮点数,最⾼的1位存储符号位S,接着的8位存储指数E,剩下的23位存储有效数字M
对于64位的浮点数,最⾼的1位存储符号位S,接着的11位存储指数E,剩下的52位存储有效数字M
画图示例:
对于指数 E来说,是一个无符号整数(unsigned int),如果E是八位,范围是0~255,如果E是11位,范围是0~2047,但是在科学计数法中E是可以为负数的,所以我们(IEEE什么协会)规定,存储E的值要加上127(如果是11位要加上1023),
比如E是10,必须保存为 10+127,那么储存在内存中的是10001001
窃窃私语:也不知道为啥这么麻烦
浮点取的过程
M取出来时,要记得加上整数部分的1,
指数E取出来有三种情况:E不全为0也不全为1 , E全为0, E全为1,
E不全为0也不全为1:
这种情况比较简单,把E取出来减127(或者1023),
E全为0:这时E的真实值就是1-127(或者1-1023)表示无限接近0的值
E全为1:这时E的真实值就是E的值就非常大了,表示无穷大的值,正负取决于符号位S
学到这里,我们已经了解了浮点数的储存,浮点数有可能不是完全精确的储存在内存中,就是会有误差,因为把小数部分转化成二进制没办法完全精确。
4.结语
讲解的不是很详尽,有不对的地方或者哪里需要补充,请在评论区留言哦!