忽略点七:结构体内存对齐原则
直到前几个星期做了一道选择题才知道,结构体元素的声明顺序可能影响结构体使用时所需的内存大小!!!
一查才知道,在C语言中结构体有内存对齐原则,这个原则可以总结为两点:
——数据成员对齐规则:
结构体或联合体的数据成员,第一个数据成员放在offset为0的地方,以后每个成员存储的起始位置为该成员大小(当该成员为基本类型时)或者该成员的最大子成员大小(当该成员为数组,结构体等时)的整数倍位置
——收尾:
结构体所占内存的总大小,必须是它内部最大成员所占内存大小的整数倍(像数组,结构体等成员在计算时按其成员的最大成员所占内存算),不是要补齐
对于以上的文字,大家可能会不理解,给大家上份代码理解一手:
struct bb {
int id; //所占内存位置为0~3
double weight; //所占内存位置为8~15
char s[10]; //所占位置为16~25
}; //整个结构体bb所占内存位置为 0~31
struct aa {
char name[2]; //所占内存位置为0~1
bb b; //所占内存位置为8~39;
int age; //所占内存位置为40~43;
}; //整个结构体aa所占内存位置0~47
在结构体bb中:
int类型id为4字节,所以占用0~3位置
double类型weight为8字节,它的起始位置必须是8的整数倍,所以它的起始位置为8,占用位置为8~15
char型数组s中最大成员单个char是1字节,所以char数组的起始位置必须是1的整数倍,所以它的起始位置为16,而数组长度为10,总占用字节为10,所以占用位置为16~25
在结构体bb中,最大成员为double型的weight(有同学会说char s[10]最大,为什么不是char s[10]?因为char s的最大成员所占内存为1,s按照1进行比较),所以结构体bb总占用内存必须为8的整数倍,所以结构体bb的总内存地址为0~31
在结构体aa中:
char型数组name数组长度为2,单个char占1字节,数组总共占两字节,所以占用位置为0~1
bb型结构体b中最大成员为double型的weight,所以bb类型的起始位置必须是8的整数倍,也就是8,而结构体bb总占用内存是32,所以占用b位置为8~39
int型age为4字节,所以起始位置必须是4的整数倍,也就是40,所以它占用的位置是40~43
在结构体aa中,最大成员是结构体b(它的最大成员weight占用内存为8),所以结构体aa总占用内存必须是8的整数倍,所以结构体aa的总内存地址为0~47
讲到这儿,我们会有一个疑问,C语言为什么要有对齐原则呢?多浪费空间呀!大家可能知道桶排这种算法,以空间换时间。对齐原则也不例外,以耗费空间为代价,来加快寻址速度。
至于原理:如果一个结构的最大成员字长为w,那么系统会假设在这种体系结构上字长为w的数据使用最频繁,优先提高对w位数据操作。所有的数据访问都以w位对齐,这样需要传输的地址位减少,寻址自然就可以加快。
那么我们可以自己设定对齐规则吗?在规定的范围内是可以的,例如:
在文件开头加 #pragma pack(1) //不对齐
#pragma pack(2) //支持1,2对齐
#pragma pack(4) //支持1,2,4对齐
#pragma pack(8) //支持1,2,4,8对齐(默认)
也就是说pack是多少,结构体中的成员它的初始位置最多是多少的倍数
嗯嗯,就酱紫~
如果有写的不对或者不全面的地方 可通过主页的联系方式进行指正,谢谢!