关于结构体大小怎样计算的文章,我想网上一搜到处都有人总结,本人之所以在此基础上还要发表这样的文章是想用最简单的计算方法来总结前人给出的结论,以致我们在以后在对结构体相关编程中不会陷入字节对齐的陷阱中。想必想弄清楚这个问题的小伙伴都迫不及待了吧,废话不多说,下面分析过程。
首先大家应该知道有个叫默认对齐字节的概念吧,#pragma pack(n) 在代码中可以手动设置默认对齐字节的大小为n,VS编译器 n只能为(1、2、4、8、16)。默认为8 ,可以通过#pragma pack(show) 来看到编译的输出值为8. 在下面的讨论中我将这个默认对齐字节叫做n.
然后我们计算结构体中每个成员变量所存放位置相对于前一个的偏移量x,不同类型x值不同,如char 、short、 int、 long long x分别为1 、2 、4、8。
注意,如果n>=x, 实际偏移量 T=x, 如果 n<=x, 实际偏移量 T= n*m >=x m是使T大于等于x的最小整数。 记住这个T。
举例说明 假设n=8.
struct s { char a int b; char c; long long d; }
成员变量 | x | T |
a | 1 | 1 |
b | 4 | 4 |
c | 1 | 1 |
d | 8 | 8 |
内存分布: a T=1 字节对齐,所以暂用第1个字节
b T=4 字节对齐,b占用 4-7。
c T=1 字节对齐, c占用 8
d T= 8字节对齐, d占用9-15 。
到此,s成员变量占用16字节。
分下面两种情况:如果n大于所有成员变量类型所占用的字节数16,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数;
否则必须为n的倍数.
结论:1.想确定成员变量的对齐大小,如果比默认的对齐字节(一般是8)小,则成员变量的对齐字节就是自身的对齐字节,如果比默认的大,那么成员变量的对齐字节就是n的整数倍并且不小于自身的对齐字节。
2.根据对齐字节初步算出结构体大小m. 最后拿m如n比较,如果m>=n, 那么总大小必须为n的倍数,否则为为结构体最大成员变量的倍数。