字节对齐介绍
什么是字节对齐
内存的基本单位是 byte,64 位处理器一次可以提取 8byte(64 位)数据,32 位处理器一次读取 4byte(32 位)数据,这样计算机就会对基本的数据类型的合法地址做出一些限制,| A B C D E F G H | I G K L M M O P |。
如果希望读取 A B C D E F G H
那么读取一次就可以, I G K L M M O P
亦然,若希望读取 F G H I G K L M
那么一次读取是不可行的.必须读取两次才能得到.
对齐的规则
- 结构体变量的首地址能被对齐字节数大小整除
- 结构体每个成员相对结构体首地址的偏移都是成员大小的整数倍,如果不满足则在前一个成员结束地址后填充字节使之满足条件。
- 结构体的总大小为结构体对齐字节数大小的整数倍,如不满足最后填充字节使之满足条件。
为什么要字节对齐?
- 减少 CPU 访问内存的执行次数,提高内存系统性能,如果不对齐的情况下,如上例中读取
F G H I G K L M
,这时需要读取两次。 - 程序在某些处理器会出现意想不到的 crash。
如何对齐
- 尝试调整成员变量顺序,使之自己对齐
- 通过填充(缺点: 不同平台下需要填充的字节可能不一样)
跨平台通信
不同平台的对齐方式可能不同,所以通信时可能会发生错乱
- 可以使用 #pragma pack(N)(N 字节对齐)
#pragma pack(N) //设置 N 字节对齐
#pragma pack() //还原默认对齐
- 使用 gcc 的
__attribute__
__attribute__((aligned (n))) //让所作用的结构成员对齐在 n 字节自然边界上。如果结构中有成员的长度大于 n,则按照最大成员的长度来对齐。
__attribute__ ((packed)) //取消结构在编译过程中的优化对齐,也可以认为是 1 字节对齐。
- 填充(要根据不同平台填充不同的长度)
总结
- 结构体成员变量合理安排位置会节省空间提高性能
- 跨平台的情况下可以考虑 1 字节对齐,节省了空间但是影响访问性能
- 进行填充使之满足字节对齐的条件在不同平台需要填充不同的长度
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论