数据在内存中的存储

在计算机中,数据有整数和浮点数两种存储方式,其中,整数分为有符号整形和无符号整形两种,浮点数分为单精度与双精度两种,下面先来看一个示例代码:

#include <stdio.h>
int main()
{
	int a = 9;
	float *p = &a;
	printf("%d\n",a);
	printf("%f\n",*p);
	*p = 9.0f;
	printf("%d\n",a);
	printf("%f\n",*p);
	return 0;
}

 可以看到,输出的9和9.000000都是意料之内的,但是也输出了意料之外的0.000000和1091567616,这是为什么呢?

因为,计算机中浮点数和整数的储存方式不同,读取的方式也自然不同,下面介绍整形的存储方式:

整数的存储方式:

先来介绍无符号整数:

整数的2进制表示方法有三种,即 原码、反码和补码 三种表示方法均有符号位和数值位两部分,符号位都是⽤0表示“正”,用1表示“负”,而数值位最高位的⼀位是被当做符号位,剩余的都是数值位。

正整数的原、反、补码都相同。
负整数的三种表示方法各不相同。
原码:直接将数值按照正负数的形式翻译成⼆进制得到的就是原码。
反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。
补码:反码+1就得到补码。
对于整形来说:数据存放内存中其实存放的是补码。
为什么呢?
在计算机系统中,数值⼀律⽤补码来表示和存储。
原因在于,使用补码,可以将符号位和数值域统⼀处理;
同时,加法和减法也可以统⼀处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是
相同的,不需要额外的硬件电路。

无符号整数比较好理解,所有的数位都用来存放数字,所以只能表示非负数。在C语言中,一个char类型的无符号整数共有8位,最大可以表示2^8-1,也就是255,而有符号char类型,最高位用于存放符号,有效位只有7位,因此最大数只有2^7-1,即127,那么超过127会怎么样呢?

这里以127+1举例,如果128能够正常存下,则为128,但有符号char存不下128,127用二进制表示为01111111,如果+1,则会变成1000000,对应的原码为00000000,难道是0

吗?其实10000000会被直接解析成-128,因此127的下一个数为-128,-128再加1得到-127,此时运算又恢复正常。

#include <stdio.h>
int main()
{
	signed char a = 127;
	signed char b = 128;
	printf("%d %d\n",a,b);
	return 0;
}

浮点数的储存方式:

用%d和%f打印同样的内存空间,得到了截然不同的结果,这表明浮点数与整数的储存方式也截然不同,下面将介绍浮点数的存储方式。

根据IEEE 754标准规定,一个32位的浮点数(C语言中为float)由1位的符号位,8位的指数位和23为的有效数字位组成,以10.625为例,用二进制表示为1010.101,在二进制下,小数点左移相当于除以2,则1010.101可表示为1.010101*2^3,符号位为0,表示是一个正数;为了保证指数位为正,需要加上一个中间数,32为浮点数为127,64位浮点数为1023,此时指数位为3+127=130;由于有效数字首位为1,所以只需要储存小数点后的位即可,即010101,于是整个浮点数储存为

0 1000001001010100000000000000000

IEEE为了让浮点数可以表示所有的情况,所以把浮点数分为四种情况:规格化、非规格化、无穷大和NaN。规格化是为了表示浮点数的一般情况;非规格化是为了表示0和非常接近0的浮点数;无穷大是为了表示正负无穷大;NaN是为了表示非正常数情况,比如虚数。

以单精度浮点数float为例,float符号位占1位,指数占8位,小数位占23位。

规格化的:指数位既不为0也不为255。

非规格化:指数位全为0。

无穷大:指数全为1,小数位全为0,正负由符号位决定,1为负无穷大,0为正无穷大。

NaN:指数位全为1,小数位不为0。

回到示例代码,9的二进制为0 00000000 00000000000000000001001,以浮点数读取时,符号位为0,表示正数,指数位均为0,表示非常接近0,有效数字为00000000000000000001001,组合起来就是(-1)^0*2^(-127)*1.00000000000000000001001,这个数已经非常小了(5.89e-39),而单精度浮点数只能表示小数点后6位,因此打印出0.000000。而以浮点数储存的9.0表示为1001.0,在内存中存储为01000001000100000000000000000000,以整数形式打印时则为1091567616。

而双精度浮点数与单精度类似,不过指数位有11位,因此中间数为1023,有效数字有52位,能表示更大的浮点数。

  • 18
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值