1. 对齐
需要各类型数据按照一定的规则在内存空间上排列,而不是顺序的排放,这就是对齐。
2. 对齐的原因
最常见的是如果不按照适合其平台的要求对数据存放进行对齐排列,会造成存取效率的低下。例如:一个int型(假设32位)如果存放在偶地址开始的地方,则需要一个读周期即可;如果存放在奇地址开始的地方,则可能需要2个读周期,并且需要对2次读出的结果的高低字节进行拼凑之后才能得到该int数据。
3. 对齐的实现
四个概念值:
数据类型自身的对齐值:就是数据类型的自身对齐值。
指定对齐值:#pargma pack(value) 时的指定对齐值value。
结构体或类的自身对齐值:其成员中自身对齐值最大的那个值。
数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中较小的那个值。
有效对齐值N是最终决定数据存放地址方式的值。有效对齐值N表示“对齐在N上”,即该数据的“存放起始地址%N=0”。数据结构中的数据变量都是按定义的先后顺序来排放的,即第一个数据变量的起始地址就是数据结构的起始地址。结构体的成员变量要对齐排放,结构体本身也要根据自身的有效对齐值圆整(就是结构体成员变量占用总长度需要是对结构体有效对齐值的整数倍)。
例如:
struct A {
int a;
char b;
short c;
};
struct B {
char b;
int a;
short c;
};
对于char类型数据其自身对齐值为1,对于short类型为2,对于int,float,double则为4,单位为字节。
因此A,B用到的空间都应该是7字节,但是由于编译器要对数据成员在地址空间上进行对齐,所以sizeof(struct A)=8字节,sizeof(struct B)=12字节。
假设B从地址空间0x0000开始排放成员,环境默认对齐值为4.第一个成员b的自身对齐值为1,比默认或指定对齐值4小,所以其有效对齐值为1,且其存放地址符合0x0000%1=0;第二个成员变量a,其自身对齐值为4=默认对齐值4,所以其有效对齐值为4,且其存放地址为0x0004到0x0007(因为0x0001%4!=0,且0x0004紧靠第一个变量);第三个成员变量c自身对齐值为2<默认对齐值4,所以其有效对齐值为2,且0x0008%2=0,故c存放在0x0008到0x0009这两个字节空间中。最后再看数据结构B的自身对齐值为其变量中最大对齐值,所以就是4=默认对齐值4,所以结构体B的有效对齐值也是4.根据结构体圆整的要求0x0000到0x0009=10字节,(10+2)%4=0,所以0x000A和0x000B也被结构体B占用。故sizeof(struct B)=12,同理可得sizeof(struct A)=8。