【C++】内存对齐(转载)
总结:
作者:邹zl
链接:https://www.zhihu.com/question/27862634/answer/46556769
分析
字节对齐主要是为了提高内存的访问效率,比如intel 32位cpu,每个总线周期都是从偶地址开始读取32位的内存数据,如果数据存放地址不是从偶数开始,则可能出现需要两个总线周期才能读取到想要的数据,因此需要在内存中存放数据时进行对齐。
通常我们说字节对齐很多时候都是说struct结构体的内存对齐,比如下面的结构体:
struct A{ char a; int b; short c; }
在32位机器上char 占1个字节,int 占4个字节,short占2个字节,一共占用7个字节.但是实际真的是这样吗?
我们先看下面程序的输出:
#include <stdio.h> struct A{ char a; int b; short c; }; int main(){ struct A a; printf("A: %ld\n", sizeof(a)); return 0; }
测试输出的结果是A: 12, 比计算的7多了5个字节。这个就是因为编译器在编译的时候进行了内存对齐导致的。
内存对齐主要遵循下面三个原则:
- 结构体变量的起始地址能够被其最宽的成员大小整除
- 结构体每个成员相对于起始地址的偏移能够被其自身大小整除,如果不能则在前一个成员后面补充字节
- 结构体总体大小能够被最宽的成员的大小整除,如不能则在后面补充字节
其实这里有点不严谨,编译器在编译的时候是可以指定对齐大小的,实际使用的有效对齐其实是取指定大小和自身大小的最小值,一般默认的对齐大小是4。
再回到上面的例子,如果默认的对齐大小是4,结构体a的起始地址为0x0000,能够被最宽的数据成员大小(这里是int, 大小为4,有效对齐大小也是4)整除,姑char a的从0x0000开始存放占用一个字节即0x0000~0x0001,然后是int b,其大小为4,故要满足2,需要从0x0004开始,所以在char a后填充三个字节,因此a对齐后占用的空间是0x0000~0x0003,b占用的空间是0x0004~0x0007, 然后是short c其大小是2,故从0x0008开始占用两个字节,即0x0008~0x0009。 此时整个结构体占用的空间是0x0000~0x0009, 占用10个字节,10%4 != 0, 不满足第三个原则,所以需要在后面补充两个字节,即最后内存对齐后占用的空间是0x0000~0x000B,一共12个字节。
作者:KDF5000
链接:https://www.zhihu.com/question/27862634/answer/208895189
来源:知乎
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异