“数据在内存中的存储”——这大概是每个写代码的人迟早都要面对的话题。你可能写过很多代码,调过很多 bug,但有没有想过:一个 int 变量、一个字符串对象、一个结构体数组,它们到底在内存里是怎么摆放的?为什么同一个结构体在 64 位系统上会比 32 位系统上“胖”一圈?为什么 Redis 的 SDS 字符串要自己管理内存?为什么 JVM 要分代 GC?这些问题的答案,最终都指向同一个核心——数据在内存中的存储。
这篇文章我会从底层硬件讲到运行时模型,从字节序讲到内存泄漏排查,尽量把这块内容讲透。适合正在学习系统编程、后端开发、客户端优化的朋友,也适合那些排查内存问题排查到头秃的老手。读完你会明白,很多看似玄学的问题,背后其实都有一套清晰的规则。
1. 数据在内存中的整体认知:什么叫“存储”?
1.1 内存的本质就是一张带编号的大表格
先放下所有高深的概念,回到最朴素的视角。内存(Memory)本质上是一长串字节,每个字节都有一个唯一的地址,就像一栋大楼的每个房间都有自己的门牌号。CPU 通过地址总线找到某个地址,然后从那里读一个字节,或者写一个字节。
以 64 位系统为例,理论上地址空间是 2 的 64 次方,也就是非常大。但实际物理内存可能只有 16GB 或 32GB。这里就引入了一个关键概念:操作系统给每个进程提供的是虚拟地址空间,而不是物理内存本身。你的程序看到的地址,是操作系统和 CPU 的内存管理单元(MMU)联手编出来的一套“虚拟门牌号”。你写 int x = 10;,编译器把变量 x 映射到一个虚拟地址,运行时再把虚拟地址翻译成物理地址。
这就是数据存储的第一层规则:凡是程序里能看到的地址,都是虚拟地址。地址空间被划分成很多段——代码段、数据段、堆、栈、共享库映射区等。每个区域读写的权限不同,用途也不同,数据也就分散存储在这些区域里。理解了这一点,后面讲栈和堆的时候你会觉得特别顺。
1.2 从数据类型看存储的本质
在 C / C++、Rust、Java 这类静态类型语言里,每个变量都有明确的类型,而类型决定了这个数据占据多少字节。char 占 1 字节,int 在主流平台上占 4 字节,long long 占 8 字节。为什么要有类型?因为内存本身只是一串没有意义的字节,只有当你告诉编译器“这 4 个字节按整数来解释”,存储才有意义。
但同样一份字节,不同的解释方式会产生完全不同的结果。最典型的例子就是浮点数。一个 float 是 4 字节,但它不是直接把小数转成二进制整数,而是按照 IEEE 754 标准分成符号位、指数位和尾数位。我见过不少人在做协议解析时,直接把 4 个字节强转成 int,结果数字巨大无比,其实那是个 float。这就是“同样的二进制,不同的解释”造成的坑。
所以“数据在内存中的存储”这句话,至少要拆成两个问题来看:一是数据占多大空间、按什么格式排列;二是数据放在哪个区域、由谁管理生命周期。前者是编译器和硬件的事,后者是运行时和操作系统的事。接下来我逐个展开。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 存储格式的核心问题:字节序、大小端与内存对齐
2.1 大端小端:数据在内存里是“正着放”还是“倒着放”
先看一个最基础也最容易被忽略的问题:一个 4 字节的整数 0x12345678,在内存里到底是怎么放的?
- 大端序(Big-Endian):高位字节存低地址。内存里依次是
12 34 56 78,和人类阅读顺序一致。 - 小端序(Little-Endian):低位字节存低地址。内存里依次是
78 56 34 12,也就是反着来。
x86 和 x64 架构都是小端序,ARM 则两种都支持,但绝大多数情况下也跑在小端模式。网络协议里规定用大端序,所以你做网络数据包解析时,收到的字节流要先做一次字节序转换,ntohs、ntohl 这类函数就是干这个的。
判断当前系统是大端还是小端,在 C 里有个经典的技巧:
c复制#include <stdio.h>
int main() {
unsigned int x = 0x12345678;
unsigned char *p = (unsigned char *)&x;
if (*p == 0x78) {
printf("小端序\n");
} else if (*p == 0x12) {
printf("大端序\n");
}
return 0;
}
把整数的首地址当作 unsigned char* 解引用,取到的就是最低地址那个字节,看它到底是低位字节还是高位字节,就能判定字节序。
为什么搞出这么反直觉的小端序?因为 x86 当年设计时,希望 CPU 从低地址开始取数据的效率更高。小端序还有个好处:同样一个地址,你按 4 字节读是一个数,按 1 字节读取到的就是低 8 位,这
