重生之我在异世界学编程之C语言:数据在内存中的存储篇(下)

大家好,这里是小编的博客频道

小编的博客:就爱学编程
很高兴在CSDN这个大家庭与大家相识,希望能在这里与大家共同进步,共同收获更好的自己!!!

本文目录


那接下来就让我们开始遨游在知识的海洋!

浮点型数据在内存中的存储


引导

我们先来一个题目激一激,题目------读出下列代码运行的结果

代码:

c 复制代码
#include<stdio.h>
int main() {
	int n = 9;
	float* p = (float*) &n;

	printf("%d\n", n);
	printf("%f\n", *p);

	*p = 9.0;

	printf("%f\n", *p);
	printf("%d\n", n);
	return 0;
}

宝子们快用你们的小脑袋想一想吧!!!



















运行结果:

  • 在学习浮点型在内存中的存储之前,你是否只能准确预见第一行和第三行的输出情况?别担心,跟紧小编的步伐,来看看浮点型在内存中的存储。

正文

1.十进制浮点数转换为标准存储的二进制浮点数


(1)第一步:十进制浮点数转换为二进制浮点数
部分 转换方法
整数部分 同十进制整数转换为二进制整数一样
小数部分 根据权重进行配凑,从小数点后第一位2^-1开始
本质 都是根据权重的大小不同进行配凑

(2)第二步:二进制浮点数转换为标准储存的二进制浮点数

根据国际标准IEE(电气与电子工程协会)754 ,任意一个二进制浮点数可以表示成这样的形式:(-1)^S * M * (2)^E

元素 含义
S 表示符号位,为0则为正数,为1则为负数
M 表示有效数字,大于等于1,小于2
E 表示二进制下的指数位

例:
十进制浮点数 5.0 101.0 -1的0次方*1.01*2的2次方 S=0 -5.0 -101.0 -1的1次方*1.01*2的2次方 M=1.01 E=2 S=1


2.标准存储的二进制浮点数的存储规则

(1)第一部分:存储位置
元素 存储位置
float 32bit位
S 存放于第1个bit位
M 存放于第2个bit位~第9个bit位,8个bit位
E 存放于第10个bit位~第32个bit位,23个bit位
double 64bit位
S 存放于第1个bit位
M 存放于第2个bit位~第12个bit位,11个bit位
E 存放于第个13bit位~第64个bit位,52个bit位

实际效果:

(2)第二部分:存储的方式
元素 存储方式
S 无特殊,正常存
M 因为总是满足1<=M<2,所以我们进行存储的时候,就不用把1存入,这样就节省了一位bit位,可存的M的范围就更大了
E 较复杂,分问题和解决方案两个模块进行讲解
名称 内容
问题 首先,E在内存中存储时是一个无符号整数,只有浮点数整体才是有符号的 ,但是我们知道在科学记数法中,E存在有负数的可能
解决方案 所以我们规定:给每个实际的E值加127(对于double是1023)再存入bit位中

以float为例:
十进制数 5.0 在内存中的存储的二进制位 00100000000000000000000010000001 -5.0 10100000000000000000000010000001


通过以上的两个知识点,我们就能了解够浮点型在内存中是如何存储的,但存进去了,又该怎么读取呢?接下来就来介绍读取的方法

3.浮点数的读取规则

(1)第一部分:占位符
占位符 作用
%f 把一个数据的二进制位以单精度浮点数(float)的读取规则进行读取
%1f 把一个数据的二进制位以双精度浮点数(double)的读取规则进行读取

(2)第二部分:读取规则
以E的值划分为三种情况 读取规则
E不为全0或不为全1 (1)先把标准存储的二进制浮点数的形式 读出来:S:是0真实值符号位就为1(正数),是1真实值符号位就为-1(负数);E:先把对应区域的二进制转换成十进制数,再-127(double类型则-1023)。M:直接把对应区域的二进制转换成十进制数,再在前面加上1和小数点; (2)最后:根据十进制浮点数转换为标准存储的二进制浮点数逆推回去得到真实值(十进制浮点数)
E全为1 无穷
E全为0 无限趋近于0

学完了这些,我们再回头看看引导的那道题

代码:

c 复制代码
#include<stdio.h>
int main() {
	int n = 9;
	float* p = (float*) &n;

	printf("%d\n", n);
	printf("%f\n", *p);

	*p = 9.0;

	printf("%f\n", *p);
	printf("%d\n", n);
	return 0;
}
序号 分析
1 int n = 9; 首先我们创建了一个整型变量n,并为它分配了4个字节的内存空间
2 这4个字节,也就是32个bit位存放的二进制序列为:000000000000000000000000000001001(原码)000000000000000000000000000001001(补码)
3 float* p = (float*) &n 然后我们创建了一个浮点型指针变量float* p
4 printf("%d\n", n); 接着用了%d的占位符对整型变量n的二进制序列(补码)进行访问和打印:%d是将一个二进制数列(补码)当成有符号的整型变量,并转换为原码的十进制打印。类比到这里,就是把00000000000000000000000000001001(补码)按照有符号整型的变换规则变成00000000000000000000000000001001(原码),再转换(十进制)9进行打印
5 printf("%f\n", *p); 再接着用了%f的占位符对整型变量n的二进制序列(补码)进行访问和打印:%f是将一个二进制数列(补码)当成单精度浮点数,并转换为原码的十进制打印。类比到这里,就是把00000000000000000000000000001001(补码)按照单精度浮点数的读取规则变成(-1)^0 * 1.00000000 * 2^(-118)(二进制浮点数的标准存储形式),再转换(十进制)0.0000000......进行打印
6 *p = 9.0; 再然后使用了解引用操作符 *,对n的地址中原存的二进制序列00000000000000000000000000001001(补码)以单精度存储规则进行了重新存储:先把我们要存的9.0(十进制浮点数)变成(-1)^0 * 1.001 * 2 ^ 2 (二进制浮点数的标准存储形式),然后再转换为00010000000000000000000000000010(补码)
7 printf("%f\n", *p); 再接着用了%f的占位符对现在的n中存储的二进制(上述补码)进行访问和打印:%f是将一个二进制数列(补码)当成单精度浮点数,并转换为原码的十进制打印。类比到这里,就是把00010000000000000000000000000010(补码)按照单精度浮点数的读取规则变成(-1)^0 * 1.001 * 2 ^ 2 (二进制浮点数的标准存储形式),,再转换(十进制)9.00000000......进行打印
8 printf("%d\n", n); 最后用了%d的占位符对现在的n中存储的二进制(上述补码)进行访问和打印:%d是将一个二进制数列(补码)当成有符号的整型变量,并转换为原码的十进制打印。类比到这里,就是把00010000000000000000000000000010(补码)按照有符号整型的变换规则变成00010000000000000000000000000010(原码),再转换(十进制)1096517616进行打印

这样我们就得到了


快乐的时光总是短暂,咱们下篇博文再见啦!!!不要忘了,给小编点点赞和收藏支持一下,在此非常感谢!!!

相关推荐
轻口味几秒前
【每日学点鸿蒙知识】启动耗时分析、IDE报错、emitter内存泄漏、radio C API、SDK下载失败
c语言·华为·harmonyos
正在绘制中2 分钟前
Java重要面试名词整理(六):MongoDB
java·mongodb·面试
向宇it5 分钟前
【从零开始入门unity游戏开发之——C#篇32】C#其他不常用的泛型数据结构类、顺序存储和链式存储
java·开发语言·数据结构·unity·c#·游戏引擎
qianmoQ5 分钟前
DataCap MongoDB Driver: 全面解析MongoDB在DataCap中的使用指南
java·数据库·mongodb·datacao
我是苏苏17 分钟前
设计模式01:创建型设计模式之单例、简单工厂的使用情景及其基础Demo
java·开发语言·设计模式
get_money_36 分钟前
代码随想录Day52 101. 孤岛的总面积,102. 沉没孤岛,103. 水流问题,104.建造最大岛屿。
java·开发语言·笔记·算法·深度优先·图论
阿7_QuQ1 小时前
mac远程控制另一台mac怎么操作?
运维·服务器·macos
理想青年宁兴星1 小时前
【SpringBoot】Java中isEmpty使用不当报错空指针
java·spring boot·后端
Ven%1 小时前
llamafactory报错:双卡4090GPU,训练qwen2.5:7B、14B时报错GPU显存不足(out of memory),轻松搞定~~~
运维·服务器·人工智能·python·深度学习·机器学习·llama
硕风和炜1 小时前
【LeetCode: 3159. 查询数组中元素的出现位置 + 统计下标】
java·算法·leetcode