内存对齐的思考

内存对齐:

结构体变量的首地址是其最长基本类型成员的整数倍;

备注:编译器在给结构体开辟空间时,首先找到结构体中最宽的基本数据类型,然后寻找内存地址能是该基本数据类型的整倍的位置,作为结构体的首地址。将这个最宽的基本数据类型的大小作为上面介绍的对齐模数。

2)结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal padding);

备注:为结构体的一个成员开辟空间之前,编译器首先检查预开辟空间的首地址相对于结构体首地址的偏移是否是本成员的整数倍,若是,则存放本成员,反之,则在本成员和上一个成员之间填充一定的字节,以达到整数倍的要求,也就是将预开辟空间的首地址后移几个字节。

3)结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要,编译器会在最末一个成员之后加上填充字节 ————————来自百度百科

解释

我们先来做一个小练习:

struct LGStruct1 {
    double a; 
    char b;    
    int c;    
    short d;  
}struct1;
struct LGStruct2 {
    double a;   
    int b;     
    char c;    
    short d;   
}struct2;

这俩个结构体是否一样大?
double类型占8字节,char类型占1字节,int类型占4字节,short类型占2字节,那这俩个都一样呀,想加起来,都等于15字节呀,可是事实却不是这样的,我们来根据上面说的来计算一波:

struct LGStruct1 {
    double a; //占8字节
    char b;    //占1字节
    int c;    //占4字节
    short d;  //占2字节
}struct1;
struct LGStruct2 {
    double a;   //占8字节
    int b;      //占4字节
    char c;     //占1字节
    short d;   //占2字节
}struct2;

先算LGStruct1结构体的长度,double占8字节,在0~7位置(这个是数学模型,具体在哪得要实践),char占1字节,在8位置,int占4字节,在12~15位置,short占2字节,在16~17位置。
是不是感觉少了点东西?9~11呢?内存对齐有个公式min(m,n),m除以n等于整数的时候才可以将数据写入,上面这一段我们就可以按公式套进去,double(0,8),m=0,n=8,零也为整数,算char(8,1),8除以1等于8对吧 整数,所以填写进去,int(9,4),9不能整数除4,所以往后移(10,4)也不行,(11,4),也不行,(12,4)可以所以int12开始存,存四位,12~15,short从16开始(16,2),可以存,所以存16~17

内存分配图.png

第二个结构体呢我们来计算一波
double占8字节,在0~7位置,int占4字节在8~11位置,char占1字节,在12的位置,short占2字节,13不能整除2,所以往后移 于是是14、15。
未命名.png

这样大致的知道了内存是怎么样的存储了,那读取呢?
是按照8字节读取,还是16字节的读取呢?,看我上面的图,大致能懂,是按照8字节来读取的,而如何显示的呢?

static inline size_t align16(size_t x) {
    return (x + size_t(15)) & ~size_t(15);
}

假设x为2,2的二进制为0000 0001size_t(15)15二进制表示为0000 1111,俩者相加0001 0001 ~size_t(15)为15的取反1111 0000
余上15的取反,于是可以得出0001 0000等于16,我们可以得知,小于十六的可以通过这个表达式也能得到16字节大小的内存,那得到的内存为什么呢?就是空白内存。
这是结构体本身字节对齐,那么结构体中嵌套结构体呢?

未命名.png

通过计算得到他们本身的长度为40

struct LGStruct1 {
    double a;   // 8 (0-7)
    char b;     // 1 [8 1] (8)
    int c;      // 4 [9 4] 9 10 11 (12 13 14 15)
    short d;    // 2 [16 2] (16 17)
    struct LGStruct2{
        double a;   //8 (0-7)
        int b;      //4 (8 9 10 11)
        char c;     //1 (12)
        short d;    //2 13 (14 15) - 16
    }struct2;
}struct1;
未命名.png

我们可以得知struct2的大小为16 ,而他总的为什么为40呢?
根据内存对其原则二,LGStruct1实际的内存大小必须是LGStruct2中最大成员b的整数倍,即必须是8的整数倍,所以sizeof(LGStruct1) 的结果是 40

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。