深入理解整数和浮点数在内存中的存储

目录

一、整数的存储

1.1原码,反码,补码

1.2大小端字节序

1.3典型习题练习

二、浮点数的存储

2.1浮点数存储的国际标准

2.2浮点数如何存入内存

2.3浮点数如何取出

2.4练习

2.5浮点数间的比较


一、整数的存储

1.1原码,反码,补码

  1. 内存中存储的是补码
  2. 打印的是原码
  3. 正整数的原码反码补码相同
  4. 负整数的源码反码补码不同
  5. 源码的第一位为符号位(0为正,1为负),反码为源码的除符号位外全部取反,补码为反码+1

1.2大小端字节序

  • ⼤端(存储)模式:
    数据的低位字节保存在内存的⾼地址处,⽽数据的⾼位字节内容,保存在内存的低地址处。
  • ⼩端(存储)模式:
    数据的低位字节保存在内存的低地址处,⽽数据的⾼位字节内容,保存在内存的高地址处。

1.3典型习题练习

  • 判断当前电脑的大小端字节序
    //i的补码 :00000000 00000000 00000000 00000001
    //若为小端:00000001 00000000 00000000 00000000
    //若为大端:00000000 00000000 00000000 00000001
    int check()
    {
         int i = 1;
         return (*(char *)&i);     //强转取出第一位数
    } 
  • unsigned char与signed char
    int main()
    {
         char a= -1;    
         //-1的补码:1111 1111 1111 1111 1111 1111 1111 1111
         //a-1111 1111
         signed char b=-1;
         unsigned char c=-1;
         printf("a=%d,b=%d,c=%d",a,b,c);   //打印%d要整形提升,VS默认%d为有符号整形
         //a,b整形提升首位补符号位1,而c由于是无符号位,整形提升要补0
         return 0;
    }

  1. unsigned char的数据范围:0~255

  2. signed char的数据范围:-128~127

  3. 解题要领:内存中存储的一视同仁都为二进制。不同的数据类型只是充当读出的一个角度。

  4. 练习1

    #include <stdio.h>
    int main()
    {
         char a = -128;
         //a的补码:1000 0000
         printf("%u\n",a);
         //整形提升:1111 1111 1111 1111 1111 1111 1000 0000
         //无符号数直接打印上述数字
         return 0;
    }
    
  5. 练习2

    #include <stdio.h>
    int main()
    {
         char a = 128;
         //128的源码:0000 0000 0000 0000 0000 0000 1000 0000
         //a-1000 0000 (实际上是-128)
         printf("%u\n",a);
         //整形提升:1111 1111 1111 1111 1111 1111 1000 0000
         //无符号数直接打印上述数字
         return 0;
    }
  6. 练习3 
    int main()
    {
    	char a[1000];
    	int i;
    	for (i = 0; i < 1000; i++)
    	{
    		a[i] = -1 - i;
    	}
    	printf("%d", strlen(a));
        //代码结果为255
    	return 0;
    }

    总结:

  • 综合练习:求在 X86环境下⼩端字节序 的机器中,下面代码输出的结果

    #include <stdio.h>
    int main()
    {
        int a[4] = { 1, 2, 3, 4 };
        int *ptr1 = (int *)(&a + 1);
        int *ptr2 = (int *)((int)a + 1);
        printf("%x,%x", ptr1[-1], *ptr2);
        return 0;
    }

二、浮点数的存储

2.1浮点数存储的国际标准

根据国际标准IEEE 754

任意⼀个⼆进制浮点数V可以表⽰成下⾯的形式:

V   =  (−1) ^S ∗ M ∗ 2^E

  •  (−1)^S 表⽰符号位,当S=0,V为正数;当S=1,V为负数。
  • M 表⽰有效数字,M是⼤于等于1,⼩于2的。
  • 2^E 表⽰指数位

其他规定

  • 对于32位的浮点数,最⾼的1位存储符号位S,接着的8位存储指数E,剩下的23位存储有效数字M
  • 对于64位的浮点数,最⾼的1位存储符号位S,接着的11位存储指数E,剩下的52位存储有效数字M

2.2浮点数如何存入内存

  1. 先转为二进制,把它写成1.XXXXXXXX的形式
  2. 为节省空间,只保存小数位
  3. IEEE 754规定:存⼊内存时E的真实值必须再加上 ⼀个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。

2.3浮点数如何取出

  1. E全为0:数字趋于0,不再自动加上第⼀位的1
  2. E全为1:表⽰±⽆穷⼤
  3. E不全为0不全为1:指数E的计算值减去127/1023,得到真实值,再将有效数字M前加上第⼀位的1

2.4练习

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

 

2.5浮点数间的比较

  • 引入:
int main()
{
	double x = 1.0;
	double y = 0.1;
	printf("%.50lf\n", x - 0.9);
	printf("%0.50lf\n", y);
	return 0;
}

 

由此可见,浮点数不能直接进行比较,因为浮点数本身会有精度损失。

  • 那么如何进行比较?
  1. 自定义精度,通常采用define来定义
  2. 推荐使用系统精度(头文件<float.h>定义)

        3.代码示例(C语言)

#include<stdio.h>
#include<math.h>
#include<float.h>

int main()
{
	double x = 1.0;
	double y = 0.1;
	if ((fabs(x - 0.9) - y) < DBL_EPSILON)
	{
		printf("yes!");
	}
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值