文章目录
前言
介绍C语言中数据在内存中的存储,不同类型的数据存储方式各有不同,相关题目较为复杂,需要深入了解
一、整数存储
1、表示方法
- 原码:直接转换的二进制(最高位为符号位,0正1负)
- 例:
-5
→ 原码10000101
- 例:
- 反码:符号位不变,其余位取反
-5
→ 反码11111010
- 补码:反码+1(内存实际存储形式)
-5
→ 补码11111011
- 正数:原码=反码=补码
2、存储原因
- 统一处理符号位与数值域
- 加法器可处理减法(
A - B = A + (-B的补码)
) - 补码与原码转换逻辑一致,节省硬件
3、练习题解析
练习1: char a=-1; signed char b=-1; unsigned char c=-1;
printf("a=%d,b=%d,c=%d",a,b,c); // 输出:a=-1,b=-1,c=255
解析:
a
,b
是有符号 char:-1
补码11111111
→ 整型提升为0xFFFFFFFF
(-1)c
是无符号 char:11111111
→ 整型提升为0x000000FF
(255)
练习2: char a = -128;
和 char a = 128;
printf("%u\n",a); // 均输出 4294967168
解析:
-128
补码:10000000
→ 整型提升为0xFFFFFF80
(无符号值 4294967168)128
二进制10000000
→ char 截断为-128
→ 同上
练习2.3.5: char a[1000]; a[i] = -1-i;
printf("%d",strlen(a)); // 输出 255
解析:
- 数组值变化:
-1, -2, ..., -128, 127, 126, ..., 0
(strlen
遇0
停止) - 循环路径:
-128 → 127 → ... → 0
,共 255 个非零值
内存示意图:
a[0] = -1 → 0xFF
a[1] = -2 → 0xFE
...
a[127] = -128 → 0x80
a[128] = 127 → 0x7F
...
a[255] = 0 → 停止
练习2.3.6: 小端环境下 int a[4] = {1,2,3,4};
int *ptr1 = (int*)(&a + 1); // 指向数组末尾后
int *ptr2 = (int*)((int)a + 1); // 从a[0]的第二个字节开始
printf("%x,%x", ptr1[-1], *ptr2); // 输出:4, 2000000
解析:
ptr1[-1] = a[3] = 4
*ptr2
的内存解析(小端布局):a[0] 的字节:01 00 00 00 // 小端存储 0x00000001 a[1] 的字节:02 00 00 00 // 小端存储 0x00000002 从 a[0]+1 地址取4字节:00 00 00 02 → 小端解释为 0x02000000
二、大小端字节序
1、核心概念
- 大端模式:数据高位存低地址(人类阅读顺序)
例:0x1122
→ 内存:[11] [22]
- 小端模式:数据低位存低地址(计算机处理高效)
例:0x1122
→ 内存:[22] [11]
2、判断程序
// 方法1:指针强制转换
int check_sys() {
int i = 1;
return *(char*)&i; // 取首字节(小端返回1,大端返回0)
}
// 方法2:联合体共享内存
int check_sys() {
union { int i; char c; } un;
un.i = 1;
return un.c; // char c读取int的首字节
}
三、浮点数存储(IEEE 754)
1、存储公式
[ V = (-1)^S \times M \times 2^E ]
- S:符号位(1 bit)
- M:有效数字(存时省略开头的
1
) - E:指数(存时加中间值
127
/1023
)
2、内存布局
类型 | S | E | M |
---|---|---|---|
float | 1 bit | 8 bit | 23 bit |
double | 1 bit | 11 bit | 52 bit |
3、指数 E 的三种情况
- E不全0/不全1:真实值 = E - 127,M 补
1.
例:0.5
→S=0, E=126, M=0...0
- E全0:真实值 = 1-127,M 不加
1.
(表 ±0 或极小值) - E全1:表 ±∞(M全0时)
4、练习题解析
int n = 9;
float *pFloat = (float*)&n;
printf("%f\n", *pFloat); // 输出 0.000000
*pFloat = 9.0;
printf("%d\n", n); // 输出 1091567616
解析:
- 整数 9 转浮点:
- 内存
00000000 00000000 00000000 00001001
- 拆分:
S=0, E=00000000 (全0), M=000...1001
- 公式: ( V = 1.001_2 \times 2^{-126} ) → 极小值 ≈0.0
- 内存
- 浮点 9.0 转整数:
9.0 = 1.001_2 × 2^3
→S=0, E=3+127=130 (10000010), M=001...0
- 内存:
0 10000010 00100000000000000000000
- 转为整数:
01000001000100000000000000000000_2 = 1091567616
关键总结
主题 | 核心要点 | 应用场景 |
---|---|---|
整数存储 | 内存存补码,统一加减法 | 负数处理、位运算 |
大小端 | 字节序决定多字节数据排列 | 网络传输、跨平台数据解析 |
浮点数存储 | IEEE 754 三段式结构,E 需校正 | 科学计算、精度控制 |