Fork me on GitHub

内存对齐规则

要进行内存对齐,要先确定有效对齐值(也叫对齐单位)、偏移量才能进行计算,具体可以分为下面3个部分:

1、有效对其值

有效对齐值(对齐单位):是给定值#pragma pack(n) 与 结构体中最长数据类型长度,两者中较小的那个。

 

2、偏移量

偏移量可以简单的理解为:起始点到数据本身开始点之间的距离。具体为,结构体第一个成员的偏移量是0(起始点与数据本身开始点是同一个点),以后每个成员相对于结构体首地址的偏移量都是 该成员大小与有效对齐值中较小那个 的整数倍,如有需要编译器会在成员之间加上填充字节。

 

3、计算总大小

结构体的总大小为 有效对齐值 的整数倍,如有需要编译器会在最末一个成员之后加上填充字节。

 

 

下面给出几个例子以便于理解:

//32位系统
#include<stdio.h>
#pragma pack(4)

struct
{
    int E;    
    char T1;  
    char T2;  
}L1;

struct{
    char T1;  
    int E;    
    char T2;  
}L2;

struct{
    char T1;  
    char T2; 
    int E;    
}L3;

int main()
{
    printf("%d\n",sizeof(L1));  // 输出8
    printf("%d\n",sizeof(L2));  // 输出12
    printf("%d\n",sizeof(L3));  // 输出8
    return 0;
}

根据上面介绍的规则来分析一下L1、L2、L3的size大小,下面以为L1为例。

1)先确定L1的有效对齐值,#pragma pack(4)设置大小为4,L1结构体中最长数据类型长度是4(int型),有效对齐值为4。

2)逐个计算偏移量与数据大小,第一个偏移量是0,int类型大小是4,目前总大小为4。第二个成员是char类型,它与有效对齐值4相比,char是较小的,偏移量是char的整数倍(char的size是1,即1的整数倍),只需要把前面int类型偏移出来就行。因此,目前总大小为5。第三个成员也是char,偏移量是char的整数倍,只需要把前面int+char的大小偏移出来即可,所以总大小是6。

3)结构体总大小是有效对其值的整数倍,因此L1的大小需要是4的倍数,6不是4的倍数,所以要补充2个字节,总大小为8字节。

L1内存分布

 

L2中,第二个成员的偏移量是int,4的倍数,所以要填充3个字节+1个char,第三个成员的偏移量是char,1的倍数,要偏移出 填充3个字节 + 1个char + 1个int 一共8字节。目前总大小是9,9不是4的倍数,需要填充3个字节,最后总大小为12。

L2的内存分布

L3大小为8,大家可以自己计算一下。

posted @ 2022-11-15 15:01  _浮尘  阅读(310)  评论(0)    收藏  举报