前言
🎈大家好,我是何小侠🎈
🍃大家可以叫我小何或者小侠🍃
💐希望能通过写博客加深自己对于学习内容的理解💐
🌸也能帮助更多人理解和学习🌸
花繁柳密处,拨得开,才是手段;风狂雨急时,立得定,方见脚根。
解释:在花繁叶茂、柳密如织的美丽和复杂情境下,如果还能不受束缚,来去自如,才是有手段、有办法的人。在狂风骤雨的狼狈状态下还能站稳脚跟,不被吹倒,才是真正有原则的大英雄。
这篇博客我们将会了解到数据在内存中的存储方式。这对我们调试和理解内存都有很大好处。
常见的浮点数🍀
例如:1.2233344
又如:1E3
1E3我们应该好好介绍一下:
实际上就是我们初中物理中学习的科学计数法,
就等于1 x 10^3 = 1000。
还有一点规定,就是E前面的数字可以是小数,而E后面的数字只能是整数
这与我们写物理题目是一个道理,毕竟我们从来没有都不会让小数成为
10的指数。
我所使用的编译器是VS2022
,我们如果想知道我们编译器所规定的数据类型的最大值最小值
可以查找两个头文件。
limits.h
是用来查看除浮点型以外的数据类型的。
由于我们的重点是浮点数,就不一一展示了
float.h
就是用来查看编译器所设定的浮点数的最大值最小值的,但是在VS2022上很难查找到这个文件,所以我借助了everything
这个很好用的查找文件的工具。
我们已经学会了如何查看头文件,接下来我们再来看一个例子。
引例🐽
int main() { int n = 9; float *pFloat = (float *)&n; printf("n的值为:%d\n",n); printf("*pFloat的值为:%f\n",*pFloat); *pFloat = 9.0; printf("num的值为:%d\n",n); printf("*pFloat的值为:%f\n",*pFloat); return 0; }
我们看看这行代码,再分析一下。
下面是我的分析图,你也可以看看。
- 我们先看上面部分
我们printf("n的值为:%d\n", n);
这行代码是比较简单的,输出9,
那么printf("*pFloat的值为:%f\n", *pFloat);
这一行就有点不确定了,我们知道如果以%d
打印,那么我们要打印的数据在%d看来就是一个有有符号整型或者以%u
打印,那么要打印的数据在%u看来就是一个无符号的整型。
这里应该也是一样的,那么以%f
来打印,是打印9.000000吗?我们暂时放一放看下半部分。 - 下半部分
我们知道*pfloat = 9.0
会改变这两个变量里的数据,那么float *类型的是比较容易改变的,会被直接改变变成9.000000,但是int 类型的变量n呢?如果你不了解浮点数在内存中的存储,你确实很难知道为什么。
我们先将答案给出来,大家带着答案一起去寻找为什么
引例答案✳️
这真的很奇怪是不是,第二行和第三行好像是完全没有道理。但是如果你仔细一想就应该能推提出一个假设:浮点数的存储方式一定与整型不同。
别急我们马上就来介绍。
浮点数的存储规则💥
我们想搞懂这个问题需要我们了解浮点数在内存中的存储方法
放心不是很复杂,只要我们用点心。
在C语言中,浮点数的存储方式遵循IEEE 754标准。具体来说,C语言中的浮点数类型(如float、double)使用二进制表示,并按照IEEE 754标准进行存储。
IEEE 754规定:
任何一个二进制浮点数N
都可以表达成下面的方式:
(-1) ^ S * M * 2 ^ E
- 在这个式子中(-1) ^ S表示符号位,
当S为0时,N为正数,当S为1时,N为负数。
- M表示的是有效位数,大于1,小于2。
- 2 ^ E表示指数位。
这样你肯定也还是不明白,没关系我们举例就行。
首先我们也还是需要复习一下我们的数学知识:
我们更仔细的来看就是这样的:
那么如果十进制是这样那么二进制呢?
当然是差不多的,我们再来举个例子
如果不是很懂可以看这副图