三步解决C语⾔中struct字节对齐问题
直⼊主题,要判断⼀个结构体所占的空间⼤⼩,⼤体来说分三步⾛:
1.先确定实际对齐单位,其由以下三个因素决定
(1) CPU周期
WIN vs qt 默认8字节对齐
Linux 32位 默认4字节对齐,64位默认8字节对齐
(2) 结构体最⼤成员(基本数据类型变量)
(3) 预编译指令#pragma pack(n)⼿动设置 n--只能填1 2 4 8 16
上⾯三者取最⼩的,就是实际对齐单位(这⾥的“实际对齐单位”是我为了⽅便区分随便取的概念)
2.除结构体的第⼀个成员外,其他所有的成员的地址相对于结构体地址(即它⾸个成员的地址)的偏移量必须为实际对齐单位或⾃⾝⼤⼩的整数倍(取两者中⼩的那个)
3.结构体的整体⼤⼩必须为实际对齐单位的整数倍。
上⾯三步即是万能公式,下⾯看实际例⼦(linux 64系统下):
1.c语言struct头文件
上⾯nums中,没有⼿动设置对齐单位,linux64系统的默认对齐单位是8字节,结构体nums的最⼤成员double d占8个字节,故实际对齐字节是⼆者最⼩,即8字节。
char a放在结构体的起始地址;
short b占2个字节,2⼩于实际对齐字节8,故b的起始地址相对于a的起始地址的偏移量须为2的整数倍个字节;
int c占4个字节,4⼩于实际对齐字节8,故c 起始地址相对于a的起始地址的偏移量须为4的整数倍个字节;
double d占8个字节,8与实际对齐字节8相等,故d的起始地址相对于a的起始地址的偏移量须为8的整数倍个字节;
所以nums所占空间如下: 1(a)+1(浪费的空间,由b的起始地址决定这1字节必须腾出)+2(b)+4(c)+8(d)=16个字节
2.在上⾯结构体最后添加⼀个char数组,再看情况:
到成员double d为⽌,结构体nums占的空间是16,上⾯已经分析过,然后后⾯是⼀个char型数组,数组的类型是char[13],并不是基本数据类型,这⾥仍然当做13个char型变量来处理,char占1个字节,⼩于实际对齐字节8,所以这13个char型变量可以直接挨着double d后⾯放(最后结果看起来也就相当于整个数组挨着double d放置);所以总的空间情况是:1(a)+1(浪费空
间)+2(b)+4(c)+8(d)+13(arr)=29;但29并不满⾜上⾯三步⾛的最后⼀步:“整个结构体的⼤⼩必须是实际对齐单位的整数倍”,所以
29+3(浪费空间)=32,所以最后nums的空间情况是1(a)+1(浪费空间)+2(b)+4(c)+8(d)+13(arr)+3(浪费空间)=32字节
另外结构体嵌套结构体的字节对齐和上⾯原理⼀样,唯⼀要注意的是⼦结构体的起始地址与母结构体的起地址之间的距离必须是⼦结构体最⼤成员或者实际对齐单位(还是取两者⼩的那个)的整数倍。
输出结果:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论