面试常考,项目易错,长文详解C/C++中的字节对齐
引入主题,看代码我们先来看看以下程序
//编译器:来源:技术让梦想更伟大//作者:李肖遥#include
编译的结果如下:
文章插图
问题来了 , 两个结构体的内容一样 , 只是换了个位置 , 为什么sizeof(st)的时候大小不一样呢?
没错 , 这正是因为内存对齐的影响 , 导致的结果不同 。 对于我们大部分程序员来说 , 都不知道内存是怎么分布的 , 因为这是编译器该干的活 , 编译器把程序中的每个数据单元安排在合适的位置上 , 导致了相同的变量 , 不同声明顺序的结构体大小的不同 。
几种类型数据所占字节数int , long int , short int的宽度和机器字长及编译器有关,但一般都有以下规则(ANSI/ISO制订的)
- sizeof(short int) <= sizeof(int)
- sizeof(int) <= sizeof(long int)
- short int至少应为16位(2字节)
- long int至少应为32位
什么是对齐现代计算机中内存空间都是按照byte划分的 , 从理论上讲似乎对任何类型的变量的访问都可以从任何地址开始 , 但实际情况是在访问特定变量的时候经常在特定的内存地址访问 。
所以这就需要各类型数据按照一定的规则在空间上排列 , 而不是顺序的一个接一个的排放 , 这就是对齐 。 内存对齐又分为自然对齐和规则对齐 。
对于内存对齐问题 , 主要存在于struct和union等复合结构在内存中的分布情况 , 许多实际的计算机系统对基本类型数据在内存中存放的位置有限制 , 它们要求这些数据的首地址的值是某个数M(通常是4或8);
对于内存对齐 , 主要是为了提高程序的性能 , 数据结构 , 特别是栈 , 应尽可能在自然边界上对齐 , 经过对齐后 , cpu的内存访问速度大大提升 。
自然对齐指的是将对应变量类型存入对应地址值的内存空间 , 即数据要根据其数据类型存放到以其数据类型为倍数的地址处 。
例如char类型占1个字节空间 , 1的倍数是所有数 , 因此可以放置在任何允许地址处 , 而int类型占4个字节空间 , 以4为倍数的地址就有0,4,8等 。 编译器会优先按照自然对齐进行数据地址分配 。
规则对齐以结构体为例就是在自然对齐后 , 编译器将对自然对齐产生的空隙内存填充无效数据 , 且填充后结构体占内存空间为结构体内占内存空间最大的数据类型成员变量的整数倍
实验对比首先看这个结构体
typedef struct test_32{char a;short b;short c;char d;}test_32;
首先按照自然对齐 , 得到如下图的内存分布位置(第一个格子地址为0 , 后面递增 , 下面测试的同样)文章插图
编译器将对空白处进行无效数据填充 , 最后将得到此结构体占内存空间为8字节 , 这个数值也是最大的数据类型short的2个字节的整数倍 , 将程序编译 , 得到也是8字节的结果
如果稍微调换一下位置的结构体
typedef struct test_32{char a;char b;short c;short d;}test_32;
同样按照自然对齐如下图分布文章插图
- 徐福记联手JDL京东物流向数智化转型,首次落地智慧园区项目
- 运动计数开发项目的对抗赛:飞算全自动软件工程平台碾压传统模式
- 江北新区企业院士工作站技术攻关项目立项数位居南京第一
- 赞!盐城高新区4个项目入选省级项目立项!
- 威海高新区2项目获2020年度山东省重点研发计划(重大科技创新工程)立项支持
- 浙江公布首批“互联网+”医疗服务价格项目!适用各级公立医疗机构
- 168天封顶!投资56亿重点AI项目将在上海竣工,提供世界领先算力支撑
- 微软计划用Monarch项目取代Windows 10电子邮件客户端
- 先睹为快!青岛临空能源中心项目规划公示 总建面 16673.43㎡
- 仅用168天,商汤科技“新一代人工智能计算与赋能平台”项目结构封顶