今天来讲下数据在内存中的存储~
1.整数在内存中的存储
整数二进制有三种表示方法:原码,反码,补码。
正整数的原码,反码,补码相同。
负数的原码,反码,补码各不同。
原码:直接将数值按照正负数形式翻译成二进制得到的就是原码。
反码:将原码的符号位不变,其他位按位取反就是反码。
补码:反码+1就是补码
例子:
我们知道,int类型的数据占4个字节,即32个比特位,看下1和-1
int main()
{
int a = 1;
//00000000000000000000000000000001 --正整数原反补码相同
int b = -1;
//10000000000000000000000000000001 -- -1的原码
//11111111111111111111111111111110 -- -1的反码
//11111111111111111111111111111111 -- -1的补码 (反码取反+1)
return 0;
}
例2:
int main()
{
char a = 128;
printf("%d", a);
return 0;
}
结果:-128
为什么是-128呢?
我们知道char类型占1个字节,8个比特位,对于有符号位的char数值范围为-128~127,128明显是超出了char类型的范围,而在char中-128的二进制与a的相同,所以128会转化为-128。
例3:
可以思考一下打印的是什么?
int main()
{
char a = -1;
printf("%d\n", a);
printf("%u", a);
return 0;
}
-1
4294967295
为什么是这样呢?%d打印的是有符号的整数,而%u是打印无符号整数。
char类型要打印成%d等形式,会发生整形提升。
什么是整形提升?
整型提升是C程序设计语言中的一项规定:在表达式计算时,各种整形首先要提升为int类型。表达式的整型运算要在CPU的相应运算器件内执行,CPU内的整型运算器的操作数的字节长度一般是int 类型的字节长度,即四个字节。
注意:1.对于无符号整数提升,高位直接补0
2.对于有符号整数提升,高位补其符号位
所以
int main()
{
char a = -1;
//11111111
//11111111111111111111111111111111 -- -1补码
//10000000000000000000000000000000 --反码
//10000000000000000000000000000001 --原码 反码+1
printf("%d\n", a);
//11111111 --补码
//高位补1
//11111111111111111111111111111111 --由于打印的是无符号整数,所以并没有符号位,原码反码补码相同
printf("%u", a);
return 0;
}
2.浮点数在内存中的存储
浮点数的存储方式与整数的不相同。
浮点数的表示方式:
V=(-1)^S*M*2^E
其中(-1)^S表示符号位,M>=1,<2,2^E表示指数
浮点数 V=(-1)*S*M*2^E S为符号位,0为正,1为负
对于32位的浮点数,最高一位为符号位S,接着的8位是存储指数E,剩下的23位存储有效数字M
对于64位的浮点数,最高一位为符号位S,接着的11位是存储指数E,剩下的52位存储有效数字M
对于E不全为0或不全为1,指数可先加127(对于32位)或加1023(对于64位)
对于E全为0:指数E=1-127或1-1023,几位真实值,有效数M直接变成0.xxxxx,为了表示+-0,接近0的很小的数字
对于E全为1:表示正负无穷大(S决定正负)
注意:1.有些浮点数在内存中无法精确存储
2.double精度比float高
3.两个浮点数进行比较时--可能存在问题!
所以要比较浮点数时,最好设置一定的条件
例子:
int main()
{
int n = 10;
float* m = (float*)&n;
//00000000000000000000000000010010 --10的原反补码
//0 00000000 00000000000000000010010
//S E(全为0事,表示(-126) M
//V=(-1)^0*(0.000...10010)*2^(-126)
//无穷小
printf("%d\n", n);
printf("%f\n", *m);//%f只能精确到小数点后12位
//10.0
//10010 S=1,M=1.001,E=4 4+127=131
//0 10000011 10010000000000000000000
//01000001110010000000000000000000
*m = 10.0;
printf("%d\n", n);//打印是是一个很大的数 1,103,626,240
printf("%f", *m);//正常打印10.000000000000
}