float类型的内存布局

在C语言中,float的内存布局非常奇怪,我们写一个简单的程序来测试:

int main(int argc, char* argv[]) {
	float a = 1.0;
	int b = 1;
	return 0;
}

我们gdb调试打印



看到他的内存布局是0x3f8,特别奇怪。

float a = 1.5;

的内存布局是0x3fc。如下图:



特别奇怪。

float a = 4.0;

的内存布局又是0x408



下面解释一下float类型在内存中是怎么布局的。

浮点数在C/C++以及java中的内存布局是遵循IEEE标准的


简单解释一下,float类型是占用4个字节的,32个bit,第一位数符表示正负,1代表此浮点数是负数,0表示此浮点数事正数,接下来8位阶码表示指数位,范围为0-255,IEEE规定这个指数位减去127代表偏移,最后的23位表示小数部分,偏移为0的情况下,这23位数是这个浮点数的小数部分,比如

0x3f800000

二进制表示为

0011 1111 1000 0000 0000 0000 0000 0000

第一位是符号位0,表示正数

接下来8位 011 1111 1 是偏移位,换算成十进制是127。127-127=0位,偏移0位

接下来的是小数位:000 0000 0000 0000 0000 0000,小数位是0.

而按照规定,小数点前还有一个1,是不存储的,所以实际的小数位是1.0

当小数点大于0时,小数点向右偏移,反之,小数点向左偏移。

再看一个例子:

0x3fc00000

二进制表示为

0011 1111 1100 0000 0000 0000 0000 0000

第一位是符号位0,表示正数

接下来8位 011 1111 1 是偏移位,换算成十进制是127。127-127=0位,偏移0位

接下来的是小数位:100 0000 0000 0000 0000 0000,小数位是2^(-1)=0.5。

所以实际的小数位是1.5

可以看出小数位的计算方式,假如一个小数的计算方式比作11.1111......在计算时为:2^(1)+2^(0)+2^(-1)+2^(-2)+....

可以看出float的值是不连续的,事实上,浮点数以IEEE的标准所能精确表示的仅仅是其中的一部分。

例如0.3就不能被float精确表示,如下:

float a = 0.3;

内存中数据为:


是0x3e9999a

二进制表示为:

0011 1110 1001 1001 1001 1001 1010 0000

第一位是符号位0,表示正数

接下来8位 011 1110 1是偏移位,换算成十进制是125。125-127=-2位,向左偏移2位,是0.01

接下来的是小数位:001 1001 1001 1001 1010 0000,小数位是2^(-3)+2^(-4)+2^(-7)+2^(-8)+2^(-11)+2^(-12)+2^(-15)+2^(-16)+2^(-18)约等于0.3。




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值