深度剖析数据在内存中的存储(整型和浮点型)

我们知道一个变量的创建是要在内存中开辟空间的,空间的大小是根据不同的类型而决定的,而且不同的类型也影响着我们看待内存空间的视角。
比如:int a = 20,float b= 5.0
接下来我们看看数据在所开辟的类型中是如何存储的?

整型在内存中的存储

整型家族

char
unsigned char,signed char
short
unsigned short,signed short
int
unsigned int,signed int
long
unsigned long,signed long

原码、反码、补码
  • 原码: 直接将二进制按照正负数的形式翻译成二进制即可
  • 反码: 原码的符号位(用0表示正,用1表示负)不变,其他位依次按位取反
  • 补码: 反码加1

对整型来说:数据存放内存中其实存放的是补码(正数的原反补码都相同)
原因是:1.符号位和数值位可以统一处理。2.加法和减法可以统一处理(CPU只有加法器)。3.补码与原码相互转换,运算过程也是相同的,不需要额外的硬件电路。
16进制存放在这里插入图片描述
我们发现对a和b分别存放的是补码,但顺序有点不对劲,这又是为什么呢?

大端和小端
  • 大端存储模式:数据的低位保存在内存的高地址中,数据的高位保存在内存的低地址中。

  • 小端存储模式:数据的地位保存在内存的低地址中,数据的高位保存在内存的高地址中。
    内存中从左到右依次是由低地址到高地址
    在这里插入图片描述

  • 设计一个程序来判断当前机器的字节序

#include <stdio.h>
int check()
{
	int x = 1;
	return (char)x;//强制类型转换,保留最低位的一个字节。
}

int main()
{
	int ret = check();
	if (ret == 1)
	{
		printf("小端");
	}
	else
	{
		printf("大端");
	}
	return 0;
}
下面程序输出什么?

练习题1

#include<stdio.h>
int main()
{
    char a = -1;                          
    signed char b = -1;
    unsigned char c = -1;
    printf("a=%d\nb=%d\nc=%d\n", a, b, c);
    return 0;
}

运行结果

a=-1,b=-1,c=255

解析
唯一的不同点就是a,b,c 的类型不同,输出结果却有如此大的差异。
将-1(int)2进制为11111111 11111111 11111111 11111111的值赋给char类型时首先发生的时整型的截断,char接收到的只是-1最低位的一个字节2进制为:1111 1111
printf输出时以%d的形式输出cahr类型会发生整型的提升,发生提升时,有符号数高位补符号位,无符号数高位补0。
有符号数a的补码为:11111111 11111111 11111111 11111111
有符号数b补码为:11111111 11111111 11111111 11111111
无符号数c补码为:00000000 00000000 00000000 11111111

练习题2

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

运行结果

4294967168

解析
首先根据a的原码写出a的补码
根据整型的截断,char接收到的是a最低位的一个字节 2进制为:1000 0000
打印时%u为无符号整型,则cahr a发生整型提升 无符号数a的补码为:11111111 11111111 11111111 10000000无符号数的补码=原码。

练习题3

#include<stdio.h>
#include<string.h>
int main()
{
    char a[1000];
    int i;
    for (i = 0; i < 1000; i++)
    {
        a[i] = -1 - i;
    } 
    printf("%d\n", strlen(a));
    return 0;
}

运行结果

255

解析
strlen求字符串长度,实质找的是’\0’的位置,即a = 0时。
i从0开始到999,a[i]接收值从-1到-1000,char a [i]会发生整型的截断,低位一个字节为 0000 0000时,即求出字符串长度。(注意‘\0’不计入字符串长度)
i = 0时 -1截断之后为:1111 1111
i = 1时 -2截断之后为:1111 1110
i = 2时 -3截断之后为:1111 1101
当达到 0000 0000时i = 255(下标),则字符串长度为0到254,输出255。

浮点型在内存中的存储

浮点型家族

float,double,long double

浮点型存储的例子

在这里插入图片描述
n和*pFloat在内存中明明是同一个数,为什么整数和浮点数的解读结果会差别这么大?要理解这个结果,我们首先要搞懂浮点数在计算机内部的表示方法。

根据国际标准IEEE(电气和电子工程协会)754,任意一个二进制浮点数v可以表示为下面的形式:(-1)^s*M*2^E
(-1)^s表示符号位,当s=0时,v为正数;当s=1时,v为负数;
M表示有效数字,大于等于1小于2;
2^E表示指数位;

举例来说:
在这里插入图片描述
如何把十进制的浮点型转换为二进制呢?
例如十进制0.5转化为二进制为0.1
在这里插入图片描述
float a = 5.0存储如下 (-1)^0*1.01*2^2
在这里插入图片描述
对于双精度浮点型 S(1bit) E(11bit) M(52bit)

因为整型存储和浮点存储的规则不同,所以在输出时才会产生如此大的差别。
回到刚开始的问题:

整型9: 0000 0000 0000 0000 0000 0000 0000 1001还原为浮点型
由浮点存储规则得 指数E全为0,E=1-127,有效数字M不再加1,而是表示为0.xxxxx,浮点数V=(-1)^0*0.00000000000000000001001*2^-126=1.001*2^-146,所以用十进制小数表示为0.000000

浮点型9.0用二进制表示为1001.0
V=(-1)^0*1.001*2^3,S=0,M=1.001,E=3+127=130,存储为0 10000010 001 0000 0000 0000 0000 0000,还原为10进制为1091567616

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值