结构体的对齐问题
结构体对齐的详解
1、
`#include
typedef union{
long i;
int k[5]; //64位、32位系统的int型都是4字节(只有指针会随之改变)
char c;
}DATE; //共用体的大小以最大的计算字节数,所以该共用体为20字节大小
struct data{
int cat; //4字节
DATE cow; //20字节
double dog; //8字节
}too; //该结构体大小为32字节
int main()
{
DATE max;
printf("%d,%d,%d\n",sizeof(struct data),sizeof(max),sizeof(struct data)+sizeof(max));
return 0; //最后结果为32 20 52
}`
是不是很迷惑?为什么结构体不是60,不是36?接着往下看
2、
struct data{
//int cat;
// DATE cow;
//double dog;
char a;
double b;
char c;
}too;
char a被对齐为8,char c也被对齐为8,所以总和等于3*8=24,这是double在中间的情况
3、
(为对应顺序,我改变了一下打印顺序,现在是结构体大小在第二个数字)这一串代码,double在最后面,前面两个char 合起来被对齐为8,那么如果再在double前加一个int型呢,是会和char一起合占8字节呢还是会独占8字节呢?
4、
结果是char char int 合占一个8字节的空间,因为程序以四字节为单位顺序存放,先开辟一个四字节空间来存放char cat,这时发现后面还有char duke,发现4字节存两个char没问题,就把两个char挤在一个4字节空间里; 这时…又发现后面有一个int swag,这个4字节存了两个char还剩2字节空间了,已经不够存放int了,所以又开辟下一个4字节来存放int; 后面的double同理,所以加起来是16字节这一套理论即使在第1套代码依然是有效的,但在第2、3套代码却不适用
5、
所以按照这套理解,就会出现一个问题,看代码:
结构体的大小高达32,这是怎么得来的呢?这是因为结构体的空间开辟不是以4字节为单位开辟的了,是以8字节为单位开辟的; int cat,需要4字节,但是后面的double dog需要8字节的空间,那么只开辟一个8字节的空间肯定不够了,所以又开辟了一个8字节的空间来存放double。(注意这里首先开辟的8字节空间因为存了int,所以不足以存放新的类型double了,这时程序的操作不是先补齐已经开辟的8字节空间,而是为新的变量类型开辟新的8字节空间)之后,DATE cow本来是12字节(共用体本来9字节,但是以4字节段式存放,所以被补到12字节)大小,但是因为1个8字节空间不够,所以又开辟一个8字节空间给它,最后它占16个字节空间。 int cat 占8字节 double dog 占8字节 DATE cow 占16字节但是这一套理论又对第1套代码不适用,是不是晕了,我也很😵,再看
6
我们把double放到第一位去,结果又产生了变化,这时我深思熟路想啊想🤔,发现一个规律:超过8字节的类型—DATE的前一个类型如果不足8字节,那么就会去补齐,如果其前一个类型是double或者是8字节的类型,那么他就不会去补齐。 并且double不参与任何补齐。经过验证,我的推论适用于上诉所有情况,但还没有完结😵😵😵
7
第一种情况,DATE cow 占16字节空间,实际只有12个字节大小,这时int app刚好前一个类型的空间能够容纳它,所以它被补齐到DATE cow所在的16字节空间中;int swag和char duke,合占一个8字节空间,在double的作用范围之内,所以得出32的结果。第二种情况:DATE cow占16 + (int app+int swag)占8 + char duke占8 + double dog占8 = 40相互印证可以得到总结😎:double(8字节的类型)对其前及其后无数个字节都拥有对齐影响。但是超过8字节的DATE类型对前对后的变量类型都拥有容纳功能(当然如果融不进不必强融)。