每个特定平台的编译器都有一个默认的对齐系数,gcc中是4,VC中貌似是8。也可以通过于编译命令#pragma pack(n)来指定该系数,其中n的值经测试只能是1,2和4.
对齐规则:
1、结构体的第一个数据成员放在相对位置为0的地方,以后每个数据成员按#pragma pack(n)中n指定的值和该数据成员自身长度中比较小的那个进行对齐。
2、数据成员完成对齐后,结构体本身也要对齐,按照#pragma pack(n)中n的值和结构体数据成员中最长的长度中较小的进行对齐。
验证(环境:gcc 4.4;sizeof(char)=1;sizeof(int)=4;sizeof(short)=2;sizeof(long)=4;sizeof(long long)=8):
1、默认情况(n=4)
struct st1 {
char ch;//长度1<n,按1对齐,0%1=0,起始相对位置=0;存放区间[0]
int num;//长度4=n,按4对齐, 4%4=0,起始相对位置=4;存放区间[4,7]
long lv;//长度4=n,按4对齐,8%4=0,起始相对位置=8;存放区间[8,11]
};
整个结构体成员对齐后所占的区间为[0,8],占12个字节,接着结构体本身对齐,成员中最长的是4,n也等于4,所以结构体本身按4对齐(即对齐系数)。
整个结构体的大小 = 比整个结构体数据成员所占的总空间大或相等且和对齐系数求模结果为0、与之距离最近的数。
本例中,12%4=0,所以结构体st1占12个字节的空间。
2、#pragma pack(1)(即n=1)
struct st1 {
char ch;//长度1=n,按1对齐,0%1=0,起始相对位置=0;存放区间[0]
int num;//长度4>n,按n对齐, 1%1=0,起始相对位置=0;存放区间[1,4]
long lv;//长度4>n,按n对齐,5%1=0,起始相对位置=5;存放区间[5,8]
};
整个结构体成员对齐后所占的区间为[0,8],占9个字节,接着结构体本身对齐,成员中最长的是4,n等于1,所以结构体本身按1对齐(即对齐系数)。
整个结构体的大小 = 比整个结构体数据成员所占的总空间大或相等且和对齐系数求模结果为0、与之距离最近的数。
本例中,9%1=0,所以结构体st1占9个字节的空间。
3、#pragma pack(2)(即n=2)
struct st1 {
char ch;//长度1<n,按1对齐,0%1=0,起始相对位置=0;存放区间[0]
int num;//长度4>n,按n对齐, 2%2=0,起始相对位置=2;存放区间[2,5]
long lv;//长度4>n,按n对齐,6%2=0,起始相对位置=6;存放区间[5,8]
};
整个结构体成员对齐后所占的区间为[0,8],占9个字节,接着结构体本身对齐,成员中最长的是4,n等于2,所以结构体本身按2对齐(即对齐系数)。
整个结构体的大小 = 比整个结构体数据成员所占的总空间大或相等且和对齐系数求模结果为0、与之距离最近的数。
本例中,10%2=0,所以结构体st1占10个字节的空间。
为什么说#pragma pack(n)中n只能是1,2,4呢?
比如3,如果n=3,在编译的时候会警告“对齐边界必须是 2 的较小次方,而不是 3”,也就是说是不起作用的,按默认对齐系数对齐。
再如8,会有什么结果?看下一例:
4、#pragma pack(8)(即n=8)
struct siz {
char v1;
long long v2;
short v3;
int v4;
};
如果8起作用,分析一下:
struct siz {
char v1;//长度1<n,按1对齐,0%1=0,起始相对位置=0;存放区间[0]
long long v2;//长度8=n,按8对齐,8%8=0,起始相对位置=8;存放区间[8,15]
short v3;//长度2<n,按2对齐,16%2=0,起始相对位置=16;存放区间[16,17]
int v4;//长度4<n,按4对齐,20%4=0,起始相对位置=20;存放区间[20,23]
};
整个结构体成员对齐后所占的区间为[0,23],占24个字节,接着结构体本身对齐,成员中最长的是8,n等于8,所以结构体本身按8对齐(即对齐系数)。24%8=0,所以占24个字节。
然而,很不幸,运行的结果是20.
接下来,用默认的对齐系数4来分析一下:
struct siz {
char v1;//长度1<4,按1对齐,0%1=0,起始相对位置=0;存放区间[0]
long long v2;//长度8>4,按4对齐,4%4=0,起始相对位置=4;存放区间[4,11]
short v3;//长度2<4,按2对齐,12%2=0,起始相对位置=12;存放区间[12,13]
int v4;//长度4=4,按4对齐,16%4=0,起始相对位置=16;存放区间[16,19]
};
整个结构体成员对齐后所占的区间为[0,19],占20个字节,接着结构体本身对齐,成员中最长的是8,n等于4,所以结构体本身按4对齐(即对齐系数)。20%4=0,所以占20个字节。与运行结果一致。
综上分析,当n=8的时候gcc仍然使用的是默认的对齐系数4.
分享到:
相关推荐
Jupyter-Notebook
Jupyter-Notebook
高效甘特图模板下载-精心整理.zip
lstm Summary Framework: z = U>x, x u Uz Criteria for choosing U: • PCA: maximize projected variance • CCA: maximize projected correlation • FDA: maximize projected intraclass variance
OpenGL调试工具,适合图形开发者,包括视频开发,播放器开始以及游戏开发者。
全国行政区划shp最新图.zip
全国研究生招生与在校数据+国家线-最新.zip
Jupyter-Notebook
直播电商交流平台 SSM毕业设计 附带论文 启动教程:https://www.bilibili.com/video/BV1GK1iYyE2B
《林黛玉进贾府》课本剧剧本
2000-2020年沪深A股上市公司融资约束程度SA指数-最新数据发布.zip
PPT模版资料,PPT模版资料
CPA注会考试最新教材资料-最新发布.zip
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
内容概要:本文提供了一个完整的职工管理系统的C++源代码。通过面向对象的编程方法,实现了包括创建新职工、查询、增加、修改、删除、排序、统计以及存储和恢复职工数据在内的多个基本操作功能。该系统支持不同的用户角色(如管理员与老板),并通过菜单驱动方式让用户方便地进行相关操作。此外,还包括了错误检测机制,确保操作过程中的异常得到及时处理。 适合人群:有一定C++语言基础,特别是面向对象编程经验的程序员;企业管理人员和技术开发人员。 使用场景及目标:适用于中小型企业内部的人力资源管理部门或IT部门,用于维护员工基本信息数据库,提高工作效率。通过本项目的学习可以加深对链表、类和对象的理解。 阅读建议:建议先熟悉C++的基本语法和面向对象概念,再深入学习代码的具体实现细节。对于关键函数,比如exchange、creatilist等,应当重点关注并动手实践以加强理解。
Jupyter-Notebook
考研公共课历年真题集-最新发布.zip
Huawei-HKUST Joint Workshop on Theory for Future Wireless 15-16 September 2022 华为-香港科技大学未来无线理论联合研讨会 Speaker:Jingwen Tong
演出人员与观众疫情信息管理系统 SSM毕业设计 附带论文 启动教程:https://www.bilibili.com/video/BV1GK1iYyE2B
《林黛玉进贾府》课本剧剧本.pdf