关于内存对齐的原因有:
1、平台原因(移植原因):
不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数 据,否则抛出硬件异常。
2、性能原因:
数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内 存 访问;而对齐的内存访问仅需要一次访问。
内存对齐的概念则是:各种数据类型在空间上按一定规则排列,而不是顺序地一个接一个排列。提到一定规则,引入规则之前,先来做个概念解释:每个特定平台的编译器都有一个默认的“对齐系数”,也可叫对齐模数。而这个对齐系数,我们是可以通过代码来修改的:#pragma pack(n), 其中n就是对齐系数。
内存对齐中按照:1,2,4,8,16进行对齐
下面就引入对齐规则:
1.结构(struct)(或联合(union))的数据成员,第一个数据成员放在偏移量为0的地方,以后每个数据成员的对齐按照#pragma pack(n)指定的数值n和这个数据成员自身长度中,比较小的那个进行。
struct stu{
char c1; //1字节
short a1; //2字节
int i1; //4字节
long l1; //8字节,但是在32位系统是4字节
};
printf("size :%zu\n",sizeof(struct stu));
输出为:16
输出16;是因为char 是占一个字节的,但是它后面的short是2占字节,所以char后面补1位,int 占4字节,而它前面的2个成员变量刚好是占了4个字节,所以紧接着后面写入int类型变量,再后面的long类型是占8字节的,而它前面的所有类型之和也是8的倍数,所以也是紧接着写入long变量。所以输出16
2.结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。
struct s3
{
char a;
};
struct s4
{
char b;
};
struct s5
{
s3 _x;
s4 _y;
int i;
};
printf("S5 = %lu\n",sizeof(struct s5));
输出:8
3.当#pragma pack的n值等于或超过所有数据成员长度的时候,这个n值的大小将不产生任何效果。