已知对齐系数和未知对齐系数结构体如何内存对齐
许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地址是某个数k(通常要求为4或8的倍数),这就是所谓的内存对齐。
二.内存对齐优点:
1.平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。2.性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
已知对齐系数内存对齐
struct或者union成员对齐规则:
第一个数据成员放在offset为0的地方,对齐按照对齐系数和自身所占用的字节数中,两者比较小的那个进行对齐。
struct或者union的整体对齐规则:
在struct或者union数据成员完成各自对齐之后,struct或者union本身也要对齐,对齐按照对齐系数和struct或者union中最大数据成员长度中,比较小的那个进行。先局部成员对齐,然后再全局对齐。
例:
对齐系数为8
1.struct A
{
char a;
int b;
};
共8字节,a(1字节)占据0号单元格,b(4字节)与对齐系数取小为4,它的偏移地址必须是4的倍数,最近的4的倍数是4,所以b从4开始占4~7这4个单元格,前面的1~3三个单元格对齐。
2.对齐系数为8
struct B
{
char a;
short b;
int c;
};
共8字节,a(1字节)占据0号单元格,b(2字节)与对齐系数取小为2,它的偏移地址必须为2的倍数,最近的2的倍数为2,所以b占据2~3这两个单元格,c(4字节)与对齐系数取小为4,它的偏移地址必须为4的倍数,最近的4的倍数为4,所以c占据4~7这四个单元格。
3.对齐系数为8
struct C
{
char a;
int b;
int c;
double d;
};
共24字节,a(1字节)占据0号单元格,b(4字节)与对齐系数取小为4,它的偏移地址必须为4的倍数,最近的4的倍数为4,所以b占据4~7这两个单元格,c(4字节)与对齐系数取小为4,它的偏移地址必须为4的倍数,最近的4的倍数为4,所以c占据8~11这四个单元格,d(8字节)与对齐系数取小为8,所以d占据16~23这八个单元格。
如果在不知道当前编译器的对齐系数如何内存对齐:
结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小的整数倍开始。
在struct或者union数据成员完成各自对齐之后,struct或者union本身也要对齐,对齐按照struct或者union中(基本数据类型)最大数据成员长度中,最大的整数倍计算。
例:
1.struct D
{
char a;
int b;
short c;
};
共12字节,a(1字节)占据0号单元格,b(4字节)最近整除四的位置为4,所以b从4~7占据四个单元格,c(2字节)最近整除2的倍数为8,所以c占据8~9这两个单元格,但结构体之间也要进行对齐,最近整除四的位置为12,所以struct D占据0~11这11个单元格。
2.区分:
struct E
{
int a;
struct EE
{
char b;
int c;
}EE;
};
共12个字节,a(4字节)占据0~3这四个单元格,b(1字节)最近整除1的位置为4,所以b占据4号单元格,c(4字节)最近整除4的位置为8,所以c占据8~11这四个单元格。
struct F
{
int a;
double b;
};