关于内存对齐的几点记忆

内存对齐的四大规则:
  1. 第一个成员在与结构体变量偏移量为0的位置处。
  2. 其他成员变量要对齐到某个数字(对其数)的整数倍的地址处。对其数=编译器默认的一个对齐数与该成员大小的较小者。

vs中默认的值是8
Linux中默认的值是4

  1. 结构体总大小为最大对其数(每一个成员变量都有一个对其数)的整数倍。
  2. 如果嵌套了结构体对齐到自己的最大对其数是整数倍处,结构体的整体大小就是最大对齐数(含嵌套结构体的对齐数)的整数倍。

注:在第二条中,是该成员,是当前的那个成员,不是其他的。


另一种说法(与四大规则的含义是一样的):
  1. 对于结构的各个成员,第一个成员位于偏移为0的位置,以后每个数据成员的偏移量必须是min(#pragma pack()指定的数,这个数据成员的自身长度) 的倍数。

  2. 在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。

注: #pragma pack的用法为#pragma pack(n),n可以取值为1 2 3等,表示设置为n字节对齐


举列说明:
struct st1 
{
	char a ;
    int  b ;
   	short c ;
};

St1 :char占一个字节,起始偏移为0 ,int占4个字节,#pragma pack()指定的数与这个数据成员的自身长度之前的较小值4(VC6默认8字节对齐),所以int按4字节对齐,起始偏移必须为4的倍数,所以起始偏移为4,在char后编译器会添加3个字节的额外字节,不存放任意数据。short占2个字节,按2字节对齐,起始偏移为8,8正好是2的倍数,无须添加额外字节。到此第一次对齐结束,此时的内存状态为:

					oxxx|oooo|oo

此时共占10个字节。还要继续进行结构本身的对齐,即第二次对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,较小的那个数进行对齐,st1结构中最大数据成员长度为int,占4字节,而默认的#pragma pack指定的值为8,所以结果取两之较小数即按照4字节对齐,结构总大小必须为4的倍数,需添加2个额外字节使结构的总大小为12 。此时的内存状态为:

		oxxx|oooo|ooxx

到此内存对齐结束。St1占用了12个字节而非7个字节。

posted @ 2020-03-02 17:38  老耗子  阅读(179)  评论(0编辑  收藏  举报