C语言 结构体内存对齐 小白图解
大白话讲清楚:结构体的成员,不是紧紧挨在一起放内存,中间会有空隙(padding填充字节),这个规则就叫内存对齐。
一、一句话理解内存对齐
CPU读取内存的时候,喜欢按固定块来读(比如一次读4字节),如果数据地址刚好落在块开头,读取速度更快。
为了提速,编译器会在结构体成员之间自动塞空白字节(填充padding),这就是内存对齐。
代价:浪费一点点内存;好处:CPU读写更快。
二、核心对齐规则(精简小白版,考试就记这3条)
32位默认对齐数=4;64位默认对齐数=8。
最简单记忆口诀:
成员对齐:自己占几字节,就放在几的倍数地址;
整体对齐:结构体总大小,要等于最大成员大小的倍数。
三、例子1:最简单结构体,没有填充
struct Test1
{
char c; // char 1字节
int i; // int 4字节
};
分步拆解(64位环境,默认对齐数8)
- char:占1字节,对齐数min(1,8)=1。放在地址0。地址0是1倍数 ✅
- int:占4字节,对齐数min(4,8)=4。必须放在4的倍数地址
地址1、2、3都不是4倍数,所以地址1、2、3填充空白padding。
int从地址4开始,占用4、5、6、7。
内存布局:
地址:0 1 2 3 4 5 6 7
数据:[char] [填充] [int]
总占用:8字节
最大成员是int(4),8是4的倍数 ✅,末尾不用补。
#mermaid-svg-qVjbkZ0jAgkvWGuZ{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-qVjbkZ0jAgkvWGuZ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .error-icon{fill:#552222;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .marker.cross{stroke:#333333;}#mermaid-svg-qVjbkZ0jAgkvWGuZ svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-qVjbkZ0jAgkvWGuZ p{margin:0;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .cluster-label text{fill:#333;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .cluster-label span{color:#333;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .cluster-label span p{background-color:transparent;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .label text,#mermaid-svg-qVjbkZ0jAgkvWGuZ span{fill:#333;color:#333;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .node rect,#mermaid-svg-qVjbkZ0jAgkvWGuZ .node circle,#mermaid-svg-qVjbkZ0jAgkvWGuZ .node ellipse,#mermaid-svg-qVjbkZ0jAgkvWGuZ .node polygon,#mermaid-svg-qVjbkZ0jAgkvWGuZ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .rough-node .label text,#mermaid-svg-qVjbkZ0jAgkvWGuZ .node .label text,#mermaid-svg-qVjbkZ0jAgkvWGuZ .image-shape .label,#mermaid-svg-qVjbkZ0jAgkvWGuZ .icon-shape .label{text-anchor:middle;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .rough-node .label,#mermaid-svg-qVjbkZ0jAgkvWGuZ .node .label,#mermaid-svg-qVjbkZ0jAgkvWGuZ .image-shape .label,#mermaid-svg-qVjbkZ0jAgkvWGuZ .icon-shape .label{text-align:center;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .node.clickable{cursor:pointer;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .arrowheadPath{fill:#333333;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-qVjbkZ0jAgkvWGuZ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qVjbkZ0jAgkvWGuZ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-qVjbkZ0jAgkvWGuZ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .cluster text{fill:#333;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .cluster span{color:#333;}#mermaid-svg-qVjbkZ0jAgkvWGuZ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-qVjbkZ0jAgkvWGuZ rect.text{fill:none;stroke-width:0;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .icon-shape,#mermaid-svg-qVjbkZ0jAgkvWGuZ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .icon-shape p,#mermaid-svg-qVjbkZ0jAgkvWGuZ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .icon-shape .label rect,#mermaid-svg-qVjbkZ0jAgkvWGuZ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qVjbkZ0jAgkvWGuZ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-qVjbkZ0jAgkvWGuZ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-qVjbkZ0jAgkvWGuZ :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
内存地址
0: char c
1: padding空白
2: padding空白
3: padding空白
4~7: int i
❗误区:很多小白以为 1+4=5字节,实际占8字节!中间3个空字节。
四、例子2:调换成员顺序,大小会变!(重点)
struct Test2
{
int i; //4字节
char c; //1字节
};
- int放在地址0,占用0~3
- char放在地址4,占用地址4
现在已占用5字节。
规则3:整个结构体大小必须是最大成员(4)的倍数。5不是4倍数,末尾补3个padding。
内存布局
地址:0~3 4 5 6 7
数据:[int] [char] [末尾填充]
总大小依旧8字节。
结论:结构体成员顺序会影响结构体占用内存大小! 把大类型放前面,可以减少内存浪费。
五、例子3:包含short(2字节)加深理解
struct Test3
{
char a; //1字节
short b; //2字节
int c; //4字节
};
- a:地址0,1字节
- short对齐数=2,地址1不是2倍数 → 地址1填充1字节。short从地址2,占2、3
- int对齐数=4,地址4,占4~7
总大小8字节。
0:a | 1:填充 | 2~3:short |4~7:int
六、验证代码,复制运行看结果
#include <stdio.h>
struct Test1
{
char c;
int i;
};
int main()
{
printf("Test1结构体大小 = %zd\\n", sizeof(struct Test1));
return 0;
}
输出:Test1结构体大小 = 8
七、高频易错坑
✅ 正确:成员之间、结构体末尾,可能自动填充空白padding。
#pragma pack(1) //设置对齐数为1,取消填充,成员紧紧相邻
struct Test
{
char c;
int i;
};
//此时大小 = 1+4 =5,没有padding
#pragma pack() //恢复默认对齐
八、一句话总结
内存对齐就是编译器自动在结构体里面塞空白填充字节,保证每个成员放在对应倍数的内存地址,加快CPU读取速度;
结构体总大小必须是最大成员大小的整数倍;成员摆放顺序会影响总占用内存。



![打卡信奥刷题(3652)用C++实现信奥题 P12076 [OOI 2025] Cute Subsequences-171主机测评](https://www.171host.com/wp-content/uploads/2026/10/20261026055333-6adeeaddd0c48-220x150.png)

