前言
我们都知道,在创建一个变量的时候,编译器会自动开辟一块内存空间用于存放它,但是对于不同的数据类型,它们的存储形式也会有所不同。今天就让我们一起来学习整数和浮点数在内存中的存储
1. 整数在内存中的存储
我们都知道,一个数在计算机中的二进制表示形式,叫做这个数的机器数。机器数是带符号的,在计算机中机器数的最高位的1位是被当作符号位,用来存放符号,剩余的都是数值位
在符号位上,用 0 表示正数,用 1 表示负数
正整数的原、反、补码都相同
负整数的原、反、补码不尽相同
原码:直接将数值按照正负数形式翻译成二进制得到的就是原码
反码:原码的符号位不变,其他位次全部取反得到的就是补码
补码:反码 + 1 得到的就是补码
对于整数来说,数据在内存中都是以补码形式存放的,因为只有补码才方便机器将符号位和数值位统一处理,具体原理有些复杂,感兴趣的朋友可以自行查取资料
2. 大小端字节序和字节序判断
2.1 什么是大小端字节序
一个整数在内存中占据 4 个字节,它的大小已经超出了 1 个字节,那它的内存存储就必然需要把字节一一排序,这就是所谓的字节序。按照不同的存储顺序,我们分为大端字节序存储和小端字节序存储。
大端字节序:指的是数据的低位字节内容保存在内存的高地址处,而数据的高位字节内存则保存在内存的低地址位
小端字节序:指的是数据的低位字节内容保存在内存的低地址处,而数据的高位字节内存则保存在内存的高地址位
不同编译器不同环境的存储方式都有可能不同,我们常见的 X86 环境是小端模式,有些 ARM 处理还可以通过硬件来选择存储方式
2.2 怎么判断当前机器的字节序
思路:我们的目的是判断字节序,因此可以从内存入手,并使用字符指针强转取出高位字节,此时再来判断就轻而易举
#include <stdio.h>
int main()
{
int a = 1;
if (*((char*)&a) == 1)
printf("小端模式\n");
else
printf("大端模式\n");
return 0;
}
运行结果如下
3. 浮点数在内存中的存储
在讲这个之前,我们先来看一段代码
#include <stdio.h>
int main()
{
float a = 99.7;
printf("%f\n", a);
return 0;
}
大家可以猜一下运行结果是什么?有人可能会说,不就是 99.7 嘛,用得着猜嘛。那我只能很遗憾的告诉你,回答错误
奇了怪了,为什么会是这么个奇怪的数字呢?哎,我接下来要讲的浮点数在内存中存储就能为你答疑解惑
3.1 浮点数的存储
根据规定,任何一个二级制浮点数 V 都可以表示成下面的形式
V = (-1)^S * M * 2^E
- (-1)^S 表示符号位,当 S 等于 0 时表示正数,当 S 等于 -1 时表示负数
- M 表示有效数字,且 M 是大于 1 小于 2
- 2^E 表示指数位
举个例子:
十进制 5,写成二进制是 101,就相当于 1.01 * 2^2
此时 S = 0,M= 1.01,E = 2
对于 32 位的浮点数,最高 1 位存储符号位 S,接下来的 8 位存储指数 E,剩下的 23 位存储 M
对于 64 位的浮点数,最高 1 位存储符号位 S,接下来的 11 位存储指数 E,剩下的 23 位存储 M
32 位浮点数
3.2 浮点数存储的过程
- 因为 M 始终是大于 1 小于 2 的数,所以 M 的在存储的过程中整数部分可以省略,只保存小数部分
- 对于指数 E,在存入的过程中必须再加上一个中间数,8 位的 E 需要加上 127;11 位的 E 需要加上 1023
3.3 浮点数取出的过程
一般只看 E,E 不全为 0 或不全为 1 时,要把 E 的计算值再减去中间数(127/1023),得到真实值,再将有效数字 M 前加上第一位的 1;E 全为 0 或全为 1 的情况比较少见,表示的是无穷小和无穷大的数,无实际意义
结语
今天我们一起学习了整数和浮点数在内存中是如何存储的知识点;如有总结不到位的地方还请多多谅解,若有出现纰漏,希望大佬们看到错误之后能够在私信或评论区指正,博主会及时改正,共同进步!
欢迎各位在评论区友好讨论。如果觉得不错的话,麻烦您点个赞吧,十分感谢!