关于结构体、联合体大小的计算

前言


本文是介绍有关 C 语言中,结构体,联合体的大小计算方法。下面通过结合实例来加以理解它们是如何进行计算大小的。以下实例均在 VS 2017 环境中进行验证。如有出错或理解有误的地方,欢迎评论指出~

注:

                       数据类型         所占字节 (VS x86 环境 )
                           char                         1字节
                            int                         4字节
                           float                         4字节
                         double                         8字节

结构体的大小计算

分为两种情况:

  • 当没有定义 #pragma pack(value) 这种指定 value 字节进行对齐时,它的计算规则是:整体的大小在满足为最大数据类型所占字节的倍数下要达到所占内存最小。举例如下:
#include "stdio.h"

typedef struct
{
    char a[5];
    int b;
    double c;
}Test;

int main(void)
{
    printf("sizeof(Test) = %d\n",sizeof(Test));

    system("pause");
}

根据上述规则,由于没有指定对齐字节,则在结构体中 成员a 占5字节,成员b 占4字节,成员c 占8字节,这样的话就是5+4+8=17 字节,但是这里整体大小17字节 不是 8 的最小倍数,因此,成员a 需要补 3个空字节 进行对齐,成员b 需要补 4个空字节 进行对齐,即该结构体的大小为:5+3(空字节) +4+4(空字节)+8=24 字节,总大小是8的最小倍数且占用内存最小。运行结果如下:

 为了便于直观理解,下面我贴出它所对应的对齐示意图:

 如果上述例子中,成员a 的元素为4,则该结构体大小为:4+4+8=16 字节,符合计算规则。运行结果如下:

  • 当定义了 #pragma pack(value),以 value字节进行对齐时,它的计算规则如下:整体的大小必须为 value 的最小整数倍。举例如下:

#include "stdio.h"

#pragma pack(4)
typedef struct
{
    char a[5];
    int b;
    double c;
}Test;

int main(void)
{
    printf("sizeof(Test) = %d\n",sizeof(Test));

    system("pause");
}

根据上述例子,这里以 4字节 对齐计算,则成员a 占5字节,成员b 占4字节,成员c 占8字节,整体大小为:5+4+8=17 字节,但是不满足是 4字节 的最小倍数这一规则,因此成员a 后应补 3个空字节进行对齐,因此,该结构体大小为:5+3+4+8=20字节。运行结果如下:

 如果上述例子中改为以 2字节 进行对齐计算,则该结构体大小为:5+1(空字节)+4+8=18 字节。运行结果如下:

以上就是结构体的大小计算规则,感兴趣的朋友,可以自行举例验证。


联合体的大小计算

同样也分为两种情况:

  • 当没有定义 #pragma pack(value) 这种指定 value 字节进行对齐时,它的计算规则是:联合体中最大成员所占内存的大小且必须为最大类型所占字节的最小倍数。举例如下:

#include "stdio.h"

union
{
    char a[7];
    int b[2];
    double c;
}Test;

int main(void)
{
    printf("sizeof(Test) = %d\n",sizeof(Test));

    system("pause");
}

根据上述例子,该联合体,成员a 占7字节,成员b 占 4*2=8 字节,成员c 占8字节,最大字节数8同时也满足是 8(double型所对应的字节数)因此,根据计算规则,该联合体的大小为 8字节。运行结果如下:

如果将成员b的元素改为3,则最大成员b 占12字节,但要满足为8的最小倍数,因此该联合体的大小为 16字节。运行结果如下:

  • 当定义了 #pragma pack(value),以 value字节进行对齐时,它的计算规则如下:联合体中最大成员所占字节且必须为value的最小倍数。举例如下:

#include "stdio.h"

#pragma pack(2)
union
{
    char a[7];
    int b[3];
    double c;
}Test;

int main(void)
{
    printf("sizeof(Test) = %d\n",sizeof(Test));

    system("pause");
}

 根据上述例子,定义以2字节对齐进行计算,则最大成员b 占12字节,同时也是2的最小倍数,满足上述规则,因此该联合体的大小为 12字节。运行结果如下:

如果将成员b的元素改为2,并且以4字节对齐,则最大占 8字节,同时也是4的最小倍数,因此该联合体的大小为 8字节。运行结果如下:

同样,大家也可以自行举例验证。


结构体嵌套联合体的大小计算

同理也是分为两种情况:

  • 当没有定义 #pragma pack(value) 这种指定 value 字节进行对齐时,它的计算规则是:联合体按照最大成员所占字节且为最大数据类型所对应的字节的最小整数倍的原则进行计算,它所占的字节数与结构体中其他成员所占字节的总和应为结构体中最大数据类型所对应的字节的最小倍数。举例如下:

#include "stdio.h"

typedef struct
{
    union 
    {
        char a[10];
        int b[2];
        double c;
    }test;
    char d[5];
    int e;
    double f;
}Test;

int main(void)
{
    printf("sizeof(Test) = %d\n",sizeof(Test));

    system("pause");
}

根据上述规则,则联合体中,最大占10字节,但又要为8的最小倍数,因此联合体占16字节,然后 16+5+4+8=33 字节,不是结构体中最大数据类型 double 所对应的字节数 8的最小倍数,根据规则故结构体的大小为:16(联合体所占字节)+5+3(空字节)+4+4(空字节)+8=40 字节。运行结果如下:

  • 当定义了 #pragma pack(value),以 value字节进行对齐时,它的计算规则如下:联合体中最大成员所占字节且为value的最小整数倍,它所占的字节数与结构体其他成员所占字节数的总和为value的最小整数倍。举例如下:

#include "stdio.h"

#pragma pack(2)
typedef struct
{
    union 
    {
        char a[10];
        int b[2];
        double c;
    }test;
    char d[5];
    int e;
    double f;
}Test;

int main(void)
{
    printf("sizeof(Test) = %d\n",sizeof(Test));

    system("pause");
}

根据上述规则,则在上述嵌套中,联合体最大占10字节,且为2的最小倍数,因此联合体占10字节,然后10+5+4+8=27字节,但不是 2的最小倍数,因此如需满足上述规则,该结构体的大小应为:10(联合体所占字节) +5+1(空字节)+4+8=28 字节。运行结果如下:

同样,其他字节对齐,大家也可以自行验证。


好了,至此有关结构体、联合体以及它们之间嵌套的大小计算规律就说到这里。第一次写博客,字体,排版之类的有不美观的地方也请大家见谅,最后也希望能够帮助到有需要的朋友。欢迎大家浏览转载,本文为原创内容,原创不易,转载请务必保留原创相关信息,谢谢!

  • 38
    点赞
  • 89
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值