在我们日常敲代码的时候免不了使用整型数据及浮点型数据,各位小兄弟是否真的清楚数据在内存中是如何存储的呢?如果对这方面知识不太了解的小兄弟,别着急,跟随本篇博客一起学习C语言中数据在内存中是如何存储的。
一、整型数据在内存中的存储
int a = 10;
int b = -20;
变量 a 和变量 b 都是整型变量,内存会为 a 和 b 分配四个字节的空间。
要想弄清楚 a 和 b 在内存中是如何存储的我们要先了解 原码、反码、补码 的概念。
原码、反码、补码
计算机中的整数有三种 2进制 表示方法,即 原码、反码、补码。
三种表示方法均有 符号位 和 数值位 两部分,符号位 都是用 0 表示 “正 ”,用 1 表示 “负”,而数值位 正数 的 原码、反码、补码 三码都相同,而 负数 的三种表示方法各不相同。
原码:直接将数值按照正负数的形式翻译成2进制就可以得到原码。
反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。
补码:反码 +1 就得到补码。
※ 整数在内存中存放的是其补码的二进制序列
为什么在内存中存的是整数的补码形式呢?
在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。
【原码 ----> ( 取反,+1 ) ----> 补码】
【补码 ----> ( 取反,+1 ) ----> 原码】
10 为正数三码一致
补码为 00000000 00000000 00000000 00001010
以16进制表示为 00 00 00 0a
-20 为负数
原码为 10000000 00000000 00000000 00010100
反码为 11111111 11111111 11111111 11101011
补码为 11111111 11111111 11111111 11101100
以16进制表示为 ff ff ff ec
通过调试观察内存窗口中变量 a 和 变量 b 的存储情况,可以发现这两个变量在内存中存放的确实是其补码形式,但是存放的顺序和我们上面分析得出的顺序不一致,二者刚好是相互逆序的。
二、大端存储&小端存储
为了搞清楚上述内存存储的情况,我们需要引入新的概念 ------- 大端存储模式 和 小端存储模式
大端存储模式:把一个数据的高位字节序的内容存放在低地址处,低位字节序的内容存放在高地址处。 ( 高-->低;低 --> 高 )
小端存储模式:把一个数据的低位字节序的内容存放在低地址处,高位字节序的内容存放在高地址处。 ( 低-->低;高 --> 高 )
| 例 |
注:整型数据和浮点型数据都有大端存储和小端存储的概念;
数据在内存中以大端存储还是小端存储模式,这取决于硬件。
除了通过调试观察内存窗口这种办法外,还有没有其他办法判断当前的环境是大端模式还是小端模式存储呢?答案是有的。
下面的这几行简单的代码就能判断你当前环境是大端存储还是小端存储模式。
#include <stdio.h>
int main()
{
int a = 1;
char* p = (char*)&a;
if (*p)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
三、 浮点型数据在内存中的存储
存储规则
根据国际标准IEEE(电气和电子工程协会)754,任意一个2进制浮点数 V 可以表示成下面的形式:
V = (-1)^S * M * 2^E,其中
● (-1)^S 表示符号位,当 S = 0 时,V 为正数;当 S = 1 时,V 为负数;
● M 表示有效数字,1 ≤ M<2;
● 2^E 表示指数位;
| 例 |
10进制数0.5,其2进制形式为101.0 == 1.01×2²,即 V = (-1)⁰ * 1.01 * 2²
其中 S = 0,M = 1.01,E = 2;
10进制数-0.5,其2进制形式为-101.0 == -1.01×2²,即 V = (-1)¹ * 1.01 * 2²
其中 S = 1,M = 1.01,E = 2;
IEEE 754规定:
对于单精度浮点数,最高的1位是 符号位S,接着的8位是 指数E,剩下的23位为 有效数字M。
| 单精度浮点数存储模型 |
对于双精度浮点数,最高的1位是 符号位S,接着的11位是 指数E,剩下的52位为 有效数字M。
| 双精度浮点数存储模型 |
IEEE 754对在内存中保存 有效数字M 和 指数E,还有一些特别规定:
● 在计算机内部保存 有效数字M 时,默认这个数字的第1位总是1,因此可省去第1位的1,保留小数点后其余的数据即可 ( 这样的好处是,将小数点前的1省略掉,在有限的23或52个bit位中可以多存1位小数点后的数据,这样可以使得在内存中保存的数据精度更高 ),当读取数据时,将 M 的数据取出再加1即可。
● 在计算机内部保存 指数E 时,必须要加上一个中间值。对于单精度浮点数的指数E,在存入内存中时,要先加上127,再将计算值存入8个bit位中;对于双精度浮点数的指数E,在存入内存中时,要先加上1023,再将计算值存入11个bit位中。
IEEE 754对在内存中取出 指数E 分了三种情况:
① E不为全0或不为全1时:将E的计算值减去127( 或减去1023 ),得到真实值,再将M前加上第1位的1。
② E为全0时:E的真实值直接等于1-127( 或1-1023 ),M前不再加上第1位的1。
③ E为全1时:若M为全0,则表示±∞ ( 正负号取决于符号位S )
| 例 |
本次与大家一起探讨整型数据和浮点型数据在内存中的存储情况到这就已经接近尾声了,期待下次与你相遇。
< 你的关注,点赞,评论,收藏都是对我创作最大的鼓励 >
( 若本篇博客存在错误,望指出,感谢! )