字节对齐问题,导致的结构体大小确定,可以说困扰了很多开发人员。这是由于现代计算机考虑到取址效率、地址空间使用率、设计难易度等因素,造就的一个玩意。
如果你正好为字节对齐捉摸不透而烦恼,这一篇我相信可以帮助你彻底搞懂这回事。
【名词解释】
成员的偏移量:每个成员相对于结构体首地址的大小
成员的大小:每个成员自身类型所占的内存大小
【字节对齐公式】
结构体大小 = 最后一个成员的大小 + 最后一个成员的偏移量 + 末尾填充字节数
【两个准则】
1. 每个成员依次算:成员的偏移量 % 成员的大小 = 0,不整除时补足偏移量
2. 最后算:当前结构体大小 % 最宽的成员的大小 = 0,不整除时在末尾填充,使整除满足
【例子】
x成员偏移量记为 O(x)
x成员大小记为 S(x)
struct example
{
char a; // 1字节
char b; // 1字节
double c; // 8字节
short d; // 2字节
};
1. O(a) = 0
2. O(b) = O(a) + S(a) = 0+1 = 1,O(b) % S(b) = 1 % 1 = 0
3. O(c) = O(b) + S(b) = 1 + 1 = 2,O(c) % S(c) = 2 % 8 != 0,O(c)补足6字节,最终O(c) = 8
4. O(d) = O(c) + S(c) = 8 + 8 = 16,O(d) % S(d) = 16 % 2 = 0
5. 结构体当前大小 = O(d) + S(d) = 16 + 2 = 18
6. 结构体当前大小(18) % 最宽的成员的大小(8)!= 0,末尾填充6字节,最终结构体大小 = 24
设置系统对齐值的方法
一、 #pragma pack(n):C编译器按照n个字节对齐
#pargma pack():取消自定义字节对齐方式
二、 __attribute((aligned (n))):让所作用的结构成员对齐在n字节自然边界上。如果结构体中有成员的长度大于n,则按照最大成员的长度来对齐
__attribute__((packed)):取消结构在编译过程中的优化对齐,也可以认为是1字节对齐
一个练习
// 在32位机中
struct test
{
char a;
char b;
};
//结果为2字节
- 看到这里的你,试着用上面的公式,得出这个test结构体的大小是多少吧......