为什么要进行内存对齐
1 |
|
以上结构体变量数量类型相同,但是sizeof计算出来的却不同,计算之后:sizeof(A) is 12,sizeof(B) is 8,此时我们会发现一个问题,为什么两个一样的结构体,但是sizeof大小却不同?
答案就是内存对齐导致的结果不同
那么编译器为什么要进行内存对齐呢?本来sizeof(int + char + short)应该就是7,结果对齐之后反而更大了,为什么?
内存对齐规则
我们先来看看内存对齐的规则
第一个成员在与结构体偏移量0的地址处
其他成员变量必须是要对齐min(#pragma pack()指定的数,这个数据成员的自身长度)的倍数
在所有的数据成员完成各自对齐之后,结构或联合体本身也要进行对齐,对齐将按照 #pragram pack 指定的数值和结构或者联合体最大数据成员长度中比较小的那个 也就是 min(#pragram pack() , 长度最长的数据成员);
gcc默认对齐数为4,VS下默认对齐数为8
以第一个结构体A为例:
char占一个字节,起始偏移量为0;int占4个字节,min(8,4) = 4,所以偏移量为4,所以应该在char后面加上三个字节,不存放任何东西;short 占两个字节,min(8,2)=2,所以偏移量是2的倍数,而short偏移量是8,是2的倍数,所以无需添加任何字节;此时就像这样一样共占了10个字节:0xxx 0000 00 ;那么此时就要考虑一下结构体本身的对齐,min(8,4)=4;所以总体应该是4的倍数,所以还需要添加两个字节在最后面,所以内存存储状态变为了 0xxx 0000 00xx ,一共占据了12个字节
怎样让结构体按照指定的对齐参数进行对齐
pragram pack(4) 设定为4字节对齐
如何知道结构体中某个成员相对于结构体起始位置的偏移量
偏移量 = 成员自己的地址 - 结构体的地址
int num = (int)&s.student - (int)&s;
使用宏offsetof
格式:offsetof(结构体.结构体中的成员变量)
offsetof(s.student)