• 对C语言结构体内存对齐的理解


    参考文章:
    C语言问题集——结构体及其内存对齐
    Linux字节对齐的那些事

    linux中,默认情况下,没有默认的对齐数,结构体中各个成员的类型占内存大小就是该成员的对齐数,所以对于结构体内存对齐,有如下规则:
    1、第一个成员存放在内存偏移为0的地址处;
    2、结构体中各个成员的类型占内存大小就是该成员的对齐数,各成员存放的起始地址应该是对齐数的整数倍;
    3、整个结构体大小应该是该结构体中最大成员的对齐数的整数倍。
    引用一下第二个参考连接中的话,就是:

    二、对齐规则
    对于标准数据类型,它的地址只要是它的长度的整数倍就行了,而非标准数据类型按下面的原则对齐:    数组 :按照基本数据类型对齐,第一个对齐了后面的自然也就对齐了。 联合 :按其包含的长度最大的数据类型对齐。 结构体: 结构体中每个数据类型都要对齐。

    但是也可以通过#pragma pack (n)伪指令设置默认对齐数,例如设置为4字节对齐,通过伪指令#pragma pack ()取消默认对齐数设置。
    如果设置了默认的对齐数,对齐规则稍有变化,引用上述第二个参考连接中的描述:

    #pragma pack(n) 用来设定变量以n字节对齐方式。 n字节对齐就是说变量存放的起始地址的偏移量有两种情况:
    1、如果n大于等于该变量所占用的字节数,那么偏移量必须满足默认的对齐方式
    2、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。
    结构的总大小也有一个约束条件,如果n大于等于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数;否则必须是n的倍数。

    接下来我们用同一个结构体,在没有设置默认对齐数和设置了4字节对齐两种情况下,分别测试该结构体的内存占用情况。

    没有设置默认对齐数

    测试代码:

    #include
    
    #define offset(type, mb) (size_t)&(((type *)0)->mb)
    #define print_offset(type, mb) printf("sizeof %s: %lu, index of %s: %lu\n", #type, sizeof(type), #mb, offset(type, mb))
    
    typedef struct  test_st
    {
        char a;
        double b;
        short c;
        int d;
        double e;
        char f;
        char g;
        char h;
    }test_st;
    
    void main(void)
    {
        print_offset(test_st, a);
        print_offset(test_st, b);
        print_offset(test_st, c);
        print_offset(test_st, d);
        print_offset(test_st, e);
        print_offset(test_st, f);
        print_offset(test_st, g);
        print_offset(test_st, h);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    运行结果如下:
    root@imx8qmmek:~/111# ./a.out
    sizeof test_st_st: 40, index of a: 0
    sizeof test_st_st: 40, index of b: 8
    sizeof test_st_st: 40, index of c: 16
    sizeof test_st_st: 40, index of d: 20
    sizeof test_st_st: 40, index of e: 24
    sizeof test_st_st: 40, index of f: 32
    sizeof test_st_st: 40, index of g: 33
    sizeof test_st_st: 40, index of h: 34
    内存对齐的情况描述如下:
    在这里插入图片描述
    根据上述分析,上述结构体占40字节的内存。

    设置4字节对齐

    代码和上述差不多,就是在结构体定义的前后增加#pragma pack(4)和#pragma pack()的设置,运行结果如下:
    root@imx8qmmek:~/111# ./a.out
    sizeof test_st: 32, index of a: 0
    sizeof test_st: 32, index of b: 4
    sizeof test_st: 32, index of c: 12
    sizeof test_st: 32, index of d: 16
    sizeof test_st: 32, index of e: 20
    sizeof test_st: 32, index of f: 28
    sizeof test_st: 32, index of g: 29
    sizeof test_st: 32, index of h: 30

    从这两个实验的结果来看,确实符合上述对齐规则。

  • 相关阅读:
    Unity学习shader笔记[一百]简单焦散Caustic效果
    10月12日
    配置华为交换机SNMP服务
    OpenResty使用漏桶算法实现限流
    IDEA快捷键(windows)
    Spring Boot Bean 注入的常用方式教程
    程序员过中秋丨用代码制作一个祝福小网页(html+css)
    116. 在 SAPGUI 里使用 ABAP 报表上传 SAP UI5 应用到 ABAP 服务器
    【虹科分享】什么是Redis数据集成(RDI)?
    华为鸿蒙手表开发之动态生成二维码
  • 原文地址:https://blog.csdn.net/panfei263031/article/details/126090933