数据在内存中的存储

本文详细探讨了数据类型如整型和浮点型在内存中的存储方式,包括原码、反码、补码,大小端字节序以及浮点数的存储规则,通过示例代码展示了不同类型数据在内存中的实际表现。
摘要由CSDN通过智能技术生成


前言

本文会详细介绍数据在内存中的存储,包括整型,字符型及浮点型


一、数据类型介绍

1、数据类型的基本分类

1.1、整型分类
字符型:char unsigned char
短整型:short [int] unsigned short [int]
整型: int unsigned int
长整型:long [int] unsigned long [int]
1.2、浮点型分类
单精度浮点型 : float
双精度浮点型 : double


二、数据在内存中的存储

1、整型在内存中的存储

1.1 原码、反码、补码
整型分为符号位和数值位,符号位为0表示正数,为1表示负数。
对于正数来说,原码、反码、补码均相同,求出原码即可
对于负数来说:
原码:直接将数值按照正负形式转为二进制就是原码
反码: 符号位不变,其他位置数按位取反
补码: 反码+1得到补码
对于整型来说,数据在内存中存储的是补码

1.2求两个整型数据在内存中存储的形式

#include<stdio.h>
int main()
{
   int a = 5;
   //00000000000000000000000000000101   //补码
   //00 00 00 05
   int b = -10;
   //10000000000000000000000000001010 //原码
   //111111111111111111111111111111110101 //补码
   //111111111111111111111111111111110110 //补码
   //ff ff ff f6
   return 0;
}

在内存中,会如何存放a和b呢?
在这里插入图片描述
在这里插入图片描述
可以发现,内存中是倒着存的,为什么呢?接下来介绍大小端字节序。

2、大小端字节序

2.1大端存储和小端存储
大端存储:是指数据的低位保存在内存的高地址中,数据的高位保存在内存的低地址中
小端存储:是指数据的低位保存在内存的低地址中,数据的高位保存在内存的高地址中
上述代码是大端存储还是小端呢?显而易见,是小端存储,在这里我用一张图来说明:
在这里插入图片描述

3、一道有趣的题

#include<stdio.h>
int main()
{
	char a = -1;
	//11111111
	//整型提升后(因为是有符号数 第一位是1 补1)
	//11111111111111111111111111111111  --补码
	//10000000000000000000000000000000  --取反
	//10000000000000000000000000000001  --原码
	//则最后会输出-1
	signed char b = -1;
	//11111111
	//和 a 是一样的
	unsigned char c =-1;
	//11111111
	//整型提升后(因为是无符号数,补0)
	//00000000000000000000000011111111  -255
	printf("a=%d,b=%d,c=%d",a,b,c);// a=-1 b=-1 c=255
	return 0;
}

先分析以下代码,三个变量a ,b ,c 分别是字符型,有符号字符型和无符号字符型,在上文提到说,说数据在内存中存放的是补码,可以分析得出,-1的补码是11111111,那么,a,b,c在内存中存储的是ff。最后,要按照%d类型进行打印,在这里介绍一下%d,%d是以十进制打印有符号的整型,这个位置是字符型,就要进行整型提升(简单来说就是为了获得整型的精度,会将字符型和短整型提升为整型,参与运算。整型提升是在运算前就已经完成了。)如何提升呢?整型提升是按照变量数据类型的符号位来提升的,如果符号位是1,则补1,如果符号位是0,则补0,无符号数补0。

输出结果如下:
在这里插入图片描述


三、浮点型在内存中的存储

1、浮点型在内存中的存储规则

根据国际标准,任意进制的浮点数V可以表现为以下形式:
V=(-1)^S * M * 2^E
(-1)^S :表示符号位,S=0,表示正数,S=1,表示负数
M:表示有效数字,取值范围是大于等于1,小于2
2^E:表示指数位
例如:5.5十进制,用二进制表示就是101.1
用上面的存储规则就是这么表示:
5.5 = (-1)^ 0 * 1.011*2^2

2、float 和 double

本文着重介绍float。float是单精度浮点型,会向内存申请四个字节的空间来存储浮点数。如何存储?用一个简单的图来说明:
在这里插入图片描述
S就是表示0或者1,不细说,主要来介绍一下M和E
M:
国际规定,在标准中,默认第一位总是1,因此会把第一位舍去,保留小数点后面的,例如保存1.01,就只会保存01,当取出时,会自动在小数点前补1。
因此,舍去了第一位后,就可以保存24位有效数字。

E:
首先,E是一个无符号的整数,取值范围是0-255,有一种情况是这样,比方想表示0.5 ,转换为2进制是 0.1 这个时候就发现指数为负了,怎么办?标准规定,存入内存的数字需要加上中间数,float的中间数是127,double的中间数是1023。
E的两种特殊情况
第一:E全0
什么情况下,E会为全零,是不是原来的指数是-127,可以知道,2的-127是很小的一个数,所以这时指数的真实值就是1-127(或者1-1023),而取出来的M前面不补1而是补0,这样做是为了接近正负0
第二:E全1
这时候,有效数字全为0,表示正负无限大
比方说,就以0.5 为例,来看看内存中是如何存储的

#include<stdio.h>
int main()
{
	float a = 0.5f; //0.1 二进制表示
	//(-1)^0 * 1.0 *2^(-1)
	//S =0 M =1.0 E = -1
	//提到说,内存中是要加上中间数的127的 会存放126
	// 0 01111110 00000000000000000000000
	//如何存储(小端存放在内存中)
	//是 00 00 00 3f
	return 0;
}

3、一道有趣的题

#include<stdio.h>
int main()
{
	int n = 5;
	//00000000000000000000000000000101
	float *pn = (float*)&n;
	printf("%d\n",n);  //5
	printf("%f\n",*pn); //0.000000
	*pn = 9.0f;//二进制是 1001.0
	printf("%f\n",*pn);//9.000000
	//
	//1001.0 = (-1)^0 *1.0010*2^3
	//M = 3+127 = 130
	//0 1000001000 100000000000000000000   
	printf("%d\n",n);//会按照十进制有符号数打印存放在pn中的值  会打印 1,091,567,616
	return 0;
}

pn指向的那个地址所对应的元素,如果以浮点型输出,那么就会把内存中存放的数据当成浮点数存放的规则,第一位符号位,后面八位是指数位,最后23位是表示有效数字。这时发现,指数位全部为0,所以以%f 打印的时候,就会输出0;
同理,看看输出效果
在这里插入图片描述


四、总结

本文介绍了数据在内存中的存储,我后续还会接着这个详细介绍数据的取值范围,欢迎交流,欢迎互动,如果你觉得这篇博客还不错,麻烦您点赞关注博主,后续还会带来很多优质的博客。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值