
目录摘要一题目二内存对齐规则(改变默认对齐数)三解析题目四内存对齐的原因五节省空间的编码方式摘要本博客旨在理解内存对齐的规则是什么、为什么要对齐以及怎样节省结构体空间~一题目#includestdio.h //练习1 struct S1 { char c1; // 大小 1 int i; // 大小 4 char c2; // 大小 1 }; //练习2 struct S2 { char c1;// 大小 1 char c2;// 大小 1 int i; // 大小 4 }; struct S3 { double d; // 大小 char c; // 大小 struct S1 s1; // 嵌套结构体 struct S2 s2; // 嵌套结构体 }; int main() { printf(%d\n, sizeof(struct S1));//结构体s1的大小 printf(%d\n, sizeof(struct S2));//结构体s2的大小 printf(%d\n, sizeof(struct S3)); // 输出 return 0; }解释在我们看来两个结构体的大小都应该是6字节才对但结果为12和8这是因为结构体的大小不是直接相加就能得到的还需要经过内存对齐二内存对齐规则(改变默认对齐数)结构体的内存对齐规则如下①结构体的第一个成员对齐到和结构体变量起始位置偏移量为0的地址处。②其他成员变量要对齐到某个数字对齐数的整数倍的地址处。- 对齐数 编译器默认的一个对齐数 与 该成员变量大小的较小值(VS编译器默认对齐数为8)- Linux 下 gcc 没有默认对齐数对齐数直接就是成员自身的大小。③结构体总大小为最大对齐数结构体中每个成员变量都有一个对齐数所有对齐数中最大的的整数倍。④如果嵌套了结构体的情况嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处结构体的整体大小就是所有最大对齐数含嵌套结构体中成员的对齐数的整数倍。注②亦可以这么理解 其他成员变量要存放在偏移量为对齐数的整数倍的地址处❓️何为偏移量①偏移量就是当前地址相较于整个结构体变量起始地址的差值比如结构体的起始地址(第一个地址)的偏移量为0第二个地址的偏移量为1....②所以按照内存对齐的规则第一个变量直接从第一个地址开始放置即可需要几字节则占据几字节的空间③而下一个变量放置的时候则需要注意了假设为intint大小为4字节VS 中默认的对齐数为 8较小值(真正对齐数)为4则int需要对其到4的整数倍地址换句话说int需要对其到下一个偏移量的值为4的倍数的地址所以直接从偏移量为4开始存放int而当我们按照前面①②放置好所有变量之后此时的结构体总大小还需遵循③比如上述中此时占据了8字节了整个过程中的最大对齐数为4而8正好是4的倍数则总大小就为8三解析题目//练习1 struct S1 { char c1; int i; char c2; }; //练习2 struct S2 { char c1; char c2; int i; }; struct S3 { double d; // 大小8 char c; // 大小1 struct S1 s1; // 嵌套结构体 struct S2 s2; // 嵌套结构体 };解释❓️S1大小为什么为121按照规则①②得到上图注char类ix的对齐数为1(18)而任何偏移量值都是1的倍数故char类型都可以直接紧接着存放2再根据规则③继续分析此时共占据了9个字节而整个过程中的最大对齐数为4那离9最近的4的倍数就是12所以总大小就为12字节(后面3个字节就等于浪费了)❓️S2大小为什么为8经过规则①②得到上图再根据规则③继续分析此时占据了8个字节整个过程中的最大对齐数为4而8正好就是4的倍数所以大小为8❓️S3大小为什么为321根据规则④结构体中有结构体那么这个成员变量结构体就对齐到自己的成员中最大对齐数的整数倍处S1的最大对齐数为4则直接对其到偏移量为4的倍数的地址也就是12往下占据12个字节到偏移量为23处2同理S2的最大对齐数为4则直接从最近的4的倍数偏移量为24处往下占据8个字节3此时总大小为32字节根据规则④嵌套结构体的总大小是所有对齐数中最大对齐数的整数倍在整个过程中最大对齐数为double的8而32字节正好为8的倍数所以总大小32字节四内存对齐的原因1. 平台原因移植原因不是所有的硬件平台都能访问任意地址上的任意数据的某些硬件平台只能在某些地址处取某些特定类型的数据否则抛出硬件异常。2. 性能原因数据结构尤其是栈应该尽可能地在自然边界上对齐。原因在于为了访问未对齐的内存处理器需要作两次内存访问而对齐的内存访问仅需要一次访问。假设一个处理器总是从内存中取8个字节则地址必须是8的倍数。如果我们能保证将所有的 double 类型的数据的地址都对齐成8的倍数那么就可以用一个内存操作来读或者写值了。否则我们可能需要执行两次内存访问因为对象可能被分放在两个8字节内存块中。总体来说结构体的内存对齐是拿空间来换取时间的做法。五节省空间的编码方式❓️那在设计结构体的时候我们既要满⾜对⻬⼜要节省空间如何做到在上述例子中//练习1 struct S1 { char c1; int i; char c2; }; //练习2 struct S2 { char c1; char c2; int i; };解释二者都是两个char类型和一个int类型但是后者的空间为8更小所以让占用空间小的成员尽量集中在⼀起就可以节省空间本质原因内存对齐的补白机制。char1字节对齐数为1 → 可以放在任何地址偏移量0,1,2,3...int4字节对齐数为4 → 只能放在偏移量为0,4,8,12...的地址当你把char分散在int两边时int的4倍数对齐要求会导致中间产生未被使用的空洞补白而把char集中在一起这些空洞就可以被合并或避免。 [ 作者 ] shylyly [ 首次发布 ] 2024.3.21❌ [ 最新修改 ] 2026.10.17 [ 声明 ] 由于笔者水平有限文中难免有疏漏或不妥之处还望读者不吝赐教。