数据在内存中的存储

今天来讲下数据在内存中的存储~

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
}

  • 24
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhyhgx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值