一、整数在内存中的存储:原码、反码与补码
整数是编程中最常用的数据类型之一,但其在内存中的存储并非简单的二进制直接转换,而是涉及原码、反码和补码三种表示形式。
1. 三种表示形式的定义
整数的二进制表示有原码、反码和补码三种,均包含符号位和数值位:
- 符号位:0 表示 “正”,1 表示 “负”,位于数值位的最高位。
- 数值位:除符号位外的其余部分,用于表示数值大小。
2. 正整数与负整数的差异
-
正整数:原码、反码、补码完全相同。
例如:整数5的二进制原码为00000000 00000000 00000000 00000101(32 位),反码和补码与之一致。 -
负整数:三种形式不同,转换规则如下:
- 原码:直接将数值按正负翻译为二进制(符号位为 1)。
例如:-5的原码为10000000 00000000 00000000 00000101。 - 反码:符号位不变,其余位按位取反。
例如:-5的反码为11111111 11111111 11111111 11111010。 - 补码:反码加 1。
例如:-5的补码为11111111 11111111 11111111 11111011。
- 原码:直接将数值按正负翻译为二进制(符号位为 1)。
3. 为什么内存中存储补码?
计算机系统中,整数一律以补码存储,原因有三:
- 符号位与数值位可统一处理;
- 加法和减法可统一运算(CPU 只有加法器);
- 补码与原码的转换规则一致,无需额外硬件电路。
二、大小端字节序:数据的 “排列顺序”
当数据以多字节(如 int、long)存储时,字节的排列顺序会影响读取结果,这就是 “字节序” 问题,分为大端和小端两种模式。
1. 大端与小端的定义
- 大端字节序:数据的低位字节存于内存高地址,高位字节存于内存低地址。
- 小端字节序:数据的低位字节存于内存低地址,高位字节存于内存高地址。
2. 为什么存在字节序差异?
计算机以字节为基本存储单位,对于超过 1 字节的数据(如 16 位 short、32 位 int),需要规定字节排列顺序。这一差异源于处理器架构设计:
- x86 架构(如 PC)采用小端模式;
- KEIL C51(嵌入式)采用大端模式;
- 部分 ARM 处理器可通过硬件切换模式。
3. 如何判断当前机器的字节序?
通过代码可快速判断字节序,核心思路是利用 “多字节数据的低地址字节值”:
方法 1:指针转换
#include <stdio.h>
int check_sys()
{
int i = 1;
//取i的地址,转换为char*,仅访问第一个字节
return *(char*)&i;
}
int main()
{
if (check_sys() == 1)
{
printf("小端\n"); //小端中,1的低字节(0x01)存在低地址
}
else
{
printf("大端\n"); //大端中,1的低字节(0x01)存在高地址
}
return 0;
}
方法 2:联合体(共用内存)
#include <stdio.h>
int check_sys()
{
union
{
int i;
char c;
} un;
un.i = 1;
return un.c; //联合体中i和c共用内存,c取低地址字节
}
三、浮点数的存储:IEEE 754 标准
浮点数(如 float、double)的存储规则与整数完全不同,遵循 IEEE 754 国际标准。
1. 浮点数的表示形式
任意二进制浮点数可表示为:V=(−1)S×M×2E
- S:符号位(0 为正,1 为负);
- M:有效数字(1 ≤ M < 2,形如 1.xxxxxx);
- E:指数位(可正可负)。
2. 内存存储结构
- 32 位 float:1 位 S + 8 位 E + 23 位 M;
- 64 位 double:1 位 S + 11 位 E + 52 位 M。
3. 存储细节:M 和 E 的特殊处理
有效数字 M
- 由于 M 恒为 1.xxxxxx,存储时省略首位 1,仅存小数部分(节省 1 位空间)。例如,1.001 存储为 001(补满 23 位)。
指数 E
- 存储时:E 为无符号整数,需加 “偏移值”(32 位加 127,64 位加 1023)。例如,E=3 时,32 位存储为 3+127=130(0x82)。
- 读取时:
- 若 E 不全为 0 且不全为 1:真实值 = E - 偏移值;
- 若 E 全为 0:真实值 = 1 - 偏移值(M 为 0.xxxxxx,表示接近 0 的数);
- 若 E 全为 1:M 全 0 时表示 ± 无穷大。
4. 整数与浮点数的存储差异示例
为什么int n = 9和float* pFloat = &n的打印结果不同?
-
整数 9的二进制为
00000000 00000000 00000000 00001001,以浮点数解析时:
S=0,E=0(全 0),M=0.000...0001001,结果为接近 0 的极小值(打印为 0.000000)。 -
浮点数 9.0的存储:
9.0 的二进制为 1001.0 = 1.001×2³,因此 S=0,M=001(补 20 个 0),E=3+127=130(10000010)。
内存二进制为0 10000010 00100000000000000000000,以整数解析时为 1091567616。
总结
数据在内存中的存储是程序运行的基础:
- 整数通过补码存储,统一符号位与数值位的处理;
- 字节序决定多字节数据的排列顺序,需根据架构适配;
- 浮点数遵循 IEEE 754 标准,通过 S、M、E 的组合实现灵活表示。
理解这些规则,能帮助我们规避很多底层 bug(如字节序错误、类型转换异常),更深入地掌握编程本质。
697

被折叠的 条评论
为什么被折叠?



