内存对齐:
结构体变量的首地址是其最长基本类型成员的整数倍;
备注:编译器在给结构体开辟空间时,首先找到结构体中最宽的基本数据类型,然后寻找内存地址能是该基本数据类型的整倍的位置,作为结构体的首地址。将这个最宽的基本数据类型的大小作为上面介绍的对齐模数。
2)结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal padding);
备注:为结构体的一个成员开辟空间之前,编译器首先检查预开辟空间的首地址相对于结构体首地址的偏移是否是本成员的整数倍,若是,则存放本成员,反之,则在本成员和上一个成员之间填充一定的字节,以达到整数倍的要求,也就是将预开辟空间的首地址后移几个字节。
3)结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要,编译器会在最末一个成员之后加上填充字节 ————————来自百度百科
解释
我们先来做一个小练习:
struct LGStruct1 {
double a;
char b;
int c;
short d;
}struct1;
struct LGStruct2 {
double a;
int b;
char c;
short d;
}struct2;
这俩个结构体是否一样大?
double
类型占8字节
,char
类型占1字节
,int
类型占4字节
,short
类型占2字节
,那这俩个都一样呀,想加起来,都等于15字节呀,可是事实却不是这样的,我们来根据上面说的来计算一波:
struct LGStruct1 {
double a; //占8字节
char b; //占1字节
int c; //占4字节
short d; //占2字节
}struct1;
struct LGStruct2 {
double a; //占8字节
int b; //占4字节
char c; //占1字节
short d; //占2字节
}struct2;
先算LGStruct1
结构体的长度,double
占8字节,在0~7位置(这个是数学模型,具体在哪得要实践),char
占1字节,在8位置,int
占4字节,在12~15位置,short
占2字节,在16~17位置。
是不是感觉少了点东西?9~11呢?内存对齐有个公式min(m,n),m除以n等于整数的时候才可以将数据写入,上面这一段我们就可以按公式套进去,double
(0,8),m=0,n=8,零也为整数,算char
(8,1),8除以1等于8对吧 整数,所以填写进去,int
(9,4),9不能整数除4,所以往后移(10,4)也不行,(11,4),也不行,(12,4)可以所以int
从12
开始存,存四位,12~15
,short
从16开始(16,2),可以存,所以存16~17
第二个结构体呢我们来计算一波
double
占8字节,在0~7位置,int
占4字节在8~11位置,char
占1字节,在12的位置,short
占2字节,13不能整除2,所以往后移 于是是14、15。这样大致的知道了内存是怎么样的存储了,那读取呢?
是按照8字节读取,还是16字节的读取呢?,看我上面的图,大致能懂,是按照8字节来读取的,而如何显示的呢?
static inline size_t align16(size_t x) {
return (x + size_t(15)) & ~size_t(15);
}
假设x为2,2的二进制为0000 0001
,size_t(15)
为15
二进制表示为0000 1111
,俩者相加0001 0001
~size_t(15)
为15的取反1111 0000
余上15的取反,于是可以得出0001 0000
等于16,我们可以得知,小于十六的可以通过这个表达式也能得到16字节大小的内存,那得到的内存为什么呢?就是空白内存。
这是结构体本身字节对齐,那么结构体中嵌套结构体呢?
通过计算得到他们本身的长度为40
struct LGStruct1 {
double a; // 8 (0-7)
char b; // 1 [8 1] (8)
int c; // 4 [9 4] 9 10 11 (12 13 14 15)
short d; // 2 [16 2] (16 17)
struct LGStruct2{
double a; //8 (0-7)
int b; //4 (8 9 10 11)
char c; //1 (12)
short d; //2 13 (14 15) - 16
}struct2;
}struct1;
我们可以得知struct2的大小为16 ,而他总的为什么为40呢?
根据内存对其原则二,LGStruct1实际的内存大小必须是LGStruct2中最大成员b的整数倍,即必须是8的整数倍,所以sizeof(LGStruct1) 的结果是 40