结构体、枚举、联合三者大小的计算

结构体

结构体中的成员可以是不同的类型,那么是如何在计算机中存储尼。如果和数组一样,按照结构体成员的顺序一次存储在连续的内存空间,那么该如何访问尼,是按照一个字节一个字节的访问,还是四个字节四个字节的访问,这就存在类型差异。因此,就定义了一个对齐规则。在介绍对齐规则前,先了解一个概念——偏移量。

看这样一个结构体:

    struct s1
    {
        char c1;
        int i;
        char c2;
    };
偏移量

偏移量指的是结构体变量中成员的地址和结构体变量地址的差。因此,第一个成员变量的偏移量为0。

对齐规则
  1. 第一个成员在与结构体变量偏移量为0的地址处
  2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。对齐数 = 编译器默认的一个对齐数 与 该成员大小 的较小值。VS中的默认值为8 Linux中的默认值为4
  3. 结构体的总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍
  4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍,结构体的整体大小就是所有最大对齐数(包含嵌套结构体的对齐数)的整数倍

就上面的例子:

第一个成员变量 char c1:对齐数为1,该成员大小为1,编译器默认值为8,取最小值,1
第二个成员变量 int i :对齐数为4,该成员大小为4,编译器默认值为8,取最小值,4
第三个成员变量 char c2: 对齐数为1,该成员大小为1,编译器默认值为8,取最小值,1

这里写图片描述

    struct S2
    {
        double d;
        char c;
        int i;
    };

    struct S3
    {
        char c1;
        struct S3 s3;
        double d;
    };

上述例题中,是结构体嵌套问题
对于结构体S2,我们可以算出大小为16

第一个变量c1,对齐数为1,该成员变量大小为1,编译器默认值为8,取最小值,1
第二个变量s2,对齐数为8(取该结构体中的最大对齐数),该成员大小为16,编译器默认值为8,取最小值,8
第三个变量d, 对齐数为8,该成员大小为8,编译器默认值为8,取最小值,8
这里写图片描述

修改默认对齐数

上述的默认对齐数是可以修改的

    #pragma pack(2)//设置默认对齐数为8
    struct S1
    {
        char c1;
        int i;
        char c2;
    };
    #pragma pack()//取消设置的默认对齐数,还原为默认

枚举

枚举变量的大小为4

    enum Sex
    {
        MALE,
        FAMALE,
        SECRET,
    };

枚举{}中的内容是枚举类型的所有可能取值,也叫枚举常量,默认是从0开始,一次递增1。也可以在定义的时候赋初值。由于枚举变量的赋值,一次只能存放枚举结构中的某个常数。所以枚举变量的大小,实质是常数所占内存空间的大小,也就是4

联合(共用体)

联合也叫做共用体,就是,联合中的成员公用同一块空间

    union Un
    {
        char c;
        int i;
    };
  • 联合的大小至少是最大成员的大小

  • 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍

上述例子的大小为 4

    union Un
    {
        char c[5];
        int i;
    };

第一个变量对齐数为1,大小为5
第二个变量对齐数为4,大小为4

故最终联合体的大小为8

猜你喜欢

转载自blog.csdn.net/aixiaodeshushu/article/details/81330876