C语言结构体大小的计算方式

本文详细解读了C语言中结构体成员的偏移量计算法则,包括整数倍原则与对齐规则,通过实例演示了结构体大小的确定方法,特别关注了数组、联合体和结构内的复杂结构体。重点讲解了如何处理不同平台上的对齐差异,如Ubuntu与Windows的处理策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

法则一

遵循的法则为:结构体成员(数组除外)的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍)
下图计算出s1的大小为8字节

struct s1{
    char ch1;
    char ch2;
    int i;
};

在这里插入图片描述
首先,第一个成员ch1 的偏移量为0(可以这么理解 距离结构体头距离为0),ch1的类型为char,大小为1字节,0被认为是任何数的整数倍,所以到ch1这里大小为1;
然后ch2,ch2的偏移量是前面成员的大小和(这个大小和是遵循第一法则的前提下的大小和,不是随意加起来就行的),所以ch2的偏移量为1,1满足ch2的大小1的整数倍,所以到ch2这里大小为1+1 = 2;
最后i,int i的偏移量为1+1 = 2,但2不是int型大小4的整数倍,所以要在前面加上2,将之变为4,才满足第一法则。
综上s1的大小为1+1+2+4 = 8;

法则二

结构体大小必须所以成员(数组除外,结构体除外(好像))大小的整数倍
这种对齐方式牺牲了空间,但提高了效率。

struct s2{
    char ch1;
    int i;
    char ch2;
};

在这里插入图片描述
根据第一法则可以简单计算下s2的大小:
到ch1这里为1
到int这里为1+3+4 = 8
到ch2这里 8+1 = 9;
但是运行结果为12。
因为9不是4和1的整数倍(遵循第二法则),所以要继续偏移,直到12。

练习

struct s3{
    char ch1;
    int i;
    char str[10];
};

1+3+4+10 = 18,因为18不是4的倍数,所以要偏移到20。这里偏移到20不是因为str数组的大小为10才偏移的,是因为i的大小为4,法则一和法则二都是除数组外
当结构体里有数组的时候,数组那一成员不遵循偏移量和数组成员大小对齐法则(第一法则),直接将前面的大小加上数组的大小。 举个例子:

struct demo{
    char ch1;
    int i;
    char str[32];
};

这个demo计算到int i的时候为8,8直接加上数组大小32为40,四十正好是40的整数倍,所以demo的大小就为40。
在这里插入图片描述
再举个例子:

struct demo{
    char ch1;
    int i;
    char str[55];
};

8+55 = 63,63不是4的整数倍,所以要偏移到64,即demo的大小为64。
在这里插入图片描述

带结构体的结构体大小计算

struct s4{
    char ch;  
    int i;   
    struct s{
        char ch1;
        int j;
    }; 
    float f;
};

在这里插入图片描述
害,这里我就很头疼,啊哈C运行的结果和ubuntu不一样,我解释不下去了…这就是法则二上面不确定结构体除不除外的原因了。
强行解释:再ubuntu中:忽略结构体
再windows中:计算结构体。

带联合体的结构体大小计算

struct s5{
    char ch;  
    int i;   
    union{
        char ch1;
        int j;
    }; 
};

结果为12,算结构体大小的时候,如果里面有联合体,取联合体里面最大的成员计算。

带联合体的结构体大小计算

#pragma pack(4) 	//指定向4对齐  最大是double 8
struct s6{
    char ch;
    int i;
    float f;
    double d;
};

#pragma pack(4)这句话是指定计算大小的时候向4对齐
结果为20

#pragma pack(10) 	//指定向10对齐  最大是double 8
struct s7{
    char ch;
    int i;
    float f;
    double d;
};

1+3+4+4+4+8 = 24。
这一个在ubuntu中运行结果为24,没有对齐10,是因为最大时double,如果指定的比成员最大的还要大就按照成员最大的对齐。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值