• C语言 -- 内存对齐


    内存对齐

    主要内容:

      1. 结构体内存对齐规则

      2. 内存对齐规则的探讨

      3. 为什么需要内存对齐

    1. 结构体内存对齐规则

    2. 内存对齐规则的探讨

    2.1 用例代码

    struct s1{
        char a;
        int b;
        double c;
    };
    void test(){
        s1 a;
        printf("struct sizeof : %d
    ", sizeof(a));
    };

      测试结果:

        

      根据内存对齐规则对结果进行分析

        变量a是char类型,且为首成员变量,对齐到结构体内存地址的首地址处

        变量b是int类型,根据第二个规则,可得 对齐数 = (4 < 8) = 4,所以对齐到结构体内存地址为4的地址处

        变量c是double类型,同上,可得 对齐数 = (8 = 8) = 8,所以对齐到结构体内存地址为8的地址处

        从图中可以清晰看出,结构体每个变量的内存使用情况。现在结构体已经占用了16个字节,那么总结构体的大小为最大对齐数的整数倍,最大对齐数为8(c是double类型,对齐数为8),16刚好是8的整数倍,即结构体大小为16

    2.2 尝试变换一下结构体成员位置

    struct s2{
        double a;
        char b;
        int c;
    };
    void test(){
        s2 b;
        printf("struct sizeof : %d
    ", sizeof(b));
    }

      测试结果:

        

      发现和上面测试结果一样,但看下内存占用情况,内存使用情况发生了改变

     

     2.3 再次变换一下结构体成员

    struct s3{
        double a;
        int b;
        char c;
    };
    void test(){
        s3 c;
        printf("struct sizeof : %d
    ", sizeof(c));
    }

      测试结果:

        

       发现测试结果和上面还是一样,再来看看内存使用情况

      

      此时,结构体成员占用的内存空间为13个字节,但根据内存对齐规则:结构体总的大小为最大对齐数的整数倍

      当前最大对齐数为8,13不是8的整数倍,所以输出结果为16

    2.4 如果结构体嵌套使用呢?

    struct s3{
        double a;
        int b;
        char c;
    }
    struct s4{
        char c1;
        s3 a;
    }

      测试结果:

        

      根据内存对其规则:如果嵌套结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(包括嵌套结构体的对齐数)的整数倍

      分析结构体成员的内存占用情况

      

       此时,结构体成员总共占用了21个字节,根据内存对齐规则可知,结构体的大小为24

    2.5 对s4中成员和嵌套的结构体进行换位

    struct s3{
        double a;
        int b;
        char c;
    }
    struct s4{
        s3 a;
        char c1;
    }

      测试结果:

        

       分析内存占用情况:

       总计占用13个字节,最大对齐数为8,所以结构体总的大小为16

    3. 为什么需要内存对齐

    1. 平台原因(移植原因):

      不是所有的硬件平台都能访问任意地址的任意数据的;某些平台只能在某些地址处取某些特定类型的数据

    2. 性能原因:

      数据结构尤其是栈应该尽可能在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要做两次访问内存;而对齐的内存访问仅需要一次访问。

    3. 缺点:存在效率问题,这是一种以空间换时间的做法,但这种做法是值得的

  • 相关阅读:
    Echarts 实现中国地图并轮播指定的地区?
    Linux安装Zookeeper
    初遇携程apollo配置中心
    eclipse安装lombok
    依赖layui form模块 复选框tree插件(拓展可根据属性单选还是多选,数据反选)
    centos7环境下mysql5.7的安装与配置
    中文算数验证码(加减乘除)
    获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址;
    jdk自带的MD5进行数据的加密与解密
    MyBatis-plus 代码生成器
  • 原文地址:https://www.cnblogs.com/bj3251101/p/14426808.html
Copyright © 2020-2023  润新知