概念!
了解结构体对齐之前,先来了解几个概念!
对齐值 | 说明 |
---|---|
自身对齐值 | 数据成员本身的对齐值,如:char 类型占1个字节,即自身对齐值为1,short 类型占2个字节,自身对齐值为2,int 类型占4个字节,自身对齐值为4,double 类型占8个字节,自身对齐值为8; |
指定对齐值 | 1、由编译器指定:32位机是个4字节,即指定对齐值为4,64位机是个8字节,即指定对齐值为8; 2、由程序员指定: 使用#pragma pack(n) 来指定,n为2的幂次方,如1,2,4,8,16等; |
有效对齐值 | 自身对齐值 和指定对齐值 中较小的那个 ,如:32位机,char 类型,则此成员有效对齐值为1;double 类型,则此成员有效对齐值为4;如:程序员指定#pragma pack(2) ,char 类型,则此成员有效对齐值为1;double 类型,则此成员有效对齐值为2; |
这里值得一提的是指针、数组、结构体的自身对齐值以及有效对齐值;
指针: 指针存放的是地址,32位机的指针无论什么类型都是占用4个字节,其自身对齐值为4;64位机的指针则是8;
数组: 数组则是看其数据类型,如char[n]
无论n为多少,其自身对其值都为1;int[n]
无论n为多少,其自身对齐值都为4;
结构体: 结构体的自身对其值为其最大数据成员的自身对齐值,如最大数据成员为char
,则结构体的自身对齐值为1;最大数据成员为double
,则结构体的自身对齐值为8;
指针、数组、结构体的有效对齐值: 都为自身对齐值
和指定对齐值
中较小的那个;
到此,我们开始讲解规则!!!
对齐规则!
规则1:存放成员的起始地址必须为此成员有效对齐值的整数倍。
举个例子,以32位机为例:
/*假如结构体初始地址为0x0000*/
struct name{
char a; //(1)
short b; //(2)
int c; //(3)
double d; //(4)
char *e; //(5)
char f[3];//(6)
};
(1) "char a"
有效对齐值为1,此时地址为0X0000,是有效对齐值的0倍,则a存放在0x0000,占1个字节,所以下一个地址是0x0001;
(2) "short b"
有效对齐值为2,此时地址为0X0001,不是有效对齐值的整数倍,无法存放b,则要从下个是有效对齐值整数倍的地址存放,0x0002便是有效对齐值的1倍,所以b存放在0x0002,占2个字节,下一个地址是0x0004;
(3) "int c"
有效对齐值为4,此时地址为0x0004,是有效对齐值的1倍,则c存放在0x0004,占4个字节,下一个地址是0x0008;
(4) "double d"
有效对齐值为4,此时地址为0x0008,是有效对齐值的2倍,则d存放在0x0008,占8个字节,下一个地址是0x0010;
(5) "char *e"
有效对齐值为4,此时地址为0x0010,是有效对齐值的4倍,则e存放在0x0010,占4个字节,下一个地址是0x0014;
(6) "char f[3]"
有效对齐值为1,此时地址为0x0014,是有效对齐值的20倍,则f存放在0x0014,占3个字节,下一个地址是0x0017;
规则2:存放结构体的起始地址必须为此结构体有效对齐值的整数倍。
在了解这一规则前我们先来说说结构体在内存中占多少空间,像"char"
占1个字节,"int"
占4个字节等等;我们知道结构体在内存中是顺序存储的,像我们上面声明的结构体"struct name"
在内存中占24个字节"0x0000-0x0017"
,为什么不是23个字节呢,其实这跟结构体的有效对齐值
有关,结构体的大小是其有效对齐值的整数倍,这是考虑到结构体数组的原因;此时就很好理解上面的结构体为什么是占24个字节了,其有效对其值
是4,如果23个字节显然不是4的整数倍,所以需要补足1个字节,也就是24个字节了。
了解好后我们来为规则2举个例子,以32位机,还有上面声明的结构体为例:
/*假如结构体初始地址为0x0000*/
struct{
struct name a;//(1)
short b; //(2)
struct name c;//(3)
}A;
(1) "struct name a"
有效对齐值为4,此时地址为0X0000,是有效对齐值的0倍,则a存放在0x0000,占24个字节,所以下一个地址是0x0018;
(2) "short b"
有效对齐值为2,此时地址为0X0018,是有效对齐值的12倍,则b存放在0x0018,占2个字节,所以下一个地址是0x001A;
(3) "struct name c"
有效对齐值为4,此时地址为0X001A,不是有效对齐值的整数倍,无法存放c,则要从下个是有效对齐值整数倍的地址存放,0x001C便是有效对齐值的7倍,所以c存放在0x001C,占24个字节,下一个地址是0x0034;
讲到这里也就结束了,如文章有出错的地方请大佬们帮忙指点,谢谢!