我们从2011年坚守至今,只想做存粹的技术论坛。  由于网站在外面,点击附件后要很长世间才弹出下载,请耐心等待,勿重复点击不要用Edge和IE浏览器下载,否则提示不安全下载不了

 找回密码
 立即注册
搜索
查看: 1409|回复: 15

[技术文章] 探讨C语言结构体对齐问题(彻底搞清楚)

[复制链接]

该用户从未签到

5

主题

4

回帖

0

积分

一级逆天

积分
0

终身成就奖

发表于 2020-8-14 17:18:26 | 显示全部楼层 |阅读模式
写的很辛苦,都是一字一字敲出来的,希望能帮助到大家。
如果有不对的地方,欢迎大家交流。
前提条件:确认所有基本数据类型分别占用多少个字节。(这个不完全跟平台一致,不要简单地说8位机,16位机, 32位机, 64机,它还跟编译器本身密切相关)
这里就拿32位平台下,并且sizeof(char)=1, sizeof(short)=2, sizeof(int)=4 sizeof(long)=8的情况来说明。(听到32位就理所当然地说是按4字节对齐也是致命的。 )
几个注意事项:
1.  当前结构体成员本身需要几个字节来储存。(以上都有说明,看成员类型就知道了)
2.  下一个结构成员所需要的空间。(如果下一个成员占用字节较大,当前和往后都按大的字节数来对齐)
3.  当前结构体成员当中,占用最多的成员是多少个字节。(这里的“当前结构体”是指从第一个成员到正在分析的那个成员为止的结构体)
4.  正在分析的成员按新的对齐来处理后,需要填充的字节是否能够存下一个成员。如果可以,下一个成员有定义和无定义都不会对总占用
字节数产生影响。
(在分析结构所占字节数时,请按顺序进行)
下面举个例子
typedef struct
{
    char    a;
    short   b;
    int       c;
    long    d;
    char    e;
}test_t;
请问以上结构体在当前约束条件下,占用多少字节的内存空间?
分析:
从第一个成员开始:
char a;(1) 它占用一个字节, (2)它的下一个成员 short b; 需要占用2个字节 (3) 到short b;为止占用字节最多的是2字节的short b; 好,到此为止,结构会按当前占用字节数最大的成员所占用的字节数来对齐,也就是按2字节对齐,所以char a; short b;一共要占用4个字节 。
现在开始分析int c;
毫无疑问到此为止占8个字节。
同理, long d; 加入后占16字节, 但到此为止,结构体中占字节最多的是8字节的long, 所以后面增加的成员只要是在8字节以内,都得占
8字节 ,哪怕char e;只占了一个字节,因为在此之后,要按8字节来对齐了。
所以sizeof(test_t) = 2+2+4+8+8=24字节。

下面来一题,巩固一下:
typedef struct
  {
    char  a; //2 (本来占1字,因为后面的b要2字节对齐,所以要填充一个字节)
    short b; //2   (当前占四字节,后面的c也占四字节,刚好对齐,所以不用填充,就占2字节)  
    int     c; //4   (后面的d, 只占一个字节, 所以c不用填充, 但往后要按4字节对齐了)   
    char  d  //8  (如果没有后面的long e, 它是按4字节对齐至少要占用4字节,但后面来个long e, 需要填充7字节,所以d 要占用8个字节)
    long  e; //8
    char  f[9];//16
} test_t;
sizeof(test_t) = 2+2+4+8+8+16=40;
另外,如果用了#pragam pack(n)   //n为 >=0 且为2的较小次方的整数, 或者不写
那么对齐方式是按设定的来。
比如
#pragma pack(1)
typedef struct
{
    char  a;
    short b;
    int     c;
    char  d;
    long   e;
    char   f[9];
} test_t;
#pragma pack()
它按1字节对齐,只占25字节。
如果上述结构体,指定pack(2)那么它就只占28字节。

总结起来就是:
1.  当前成员占多少字节
2.  下个成员占多少字节
3.  当前和往后按多少字节对齐
4.  新的对齐方式下,当前成员填充的字节数够不够容得下下一个成员。
。。。。
1.  当前成员占多少字节
2.  下个成员占多少字节
3.  当前和往后按多少字节对齐
4.  新的对齐方式下,当前成员填充的字节数够不够容得下下一个成员。
。。。。
1.  当前成员占多少字节
2.  下个成员占多少字节
3.  当前和往后按多少字节对齐
4.  新的对齐方式下,当前成员填充的字节数够不够容得下下一个成员。
这是一个递归的过程,用好它去分析每一个成员就行了。
回复

使用道具 举报

  • TA的每日心情
    慵懒
    2024-6-14 16:03
  • 签到天数: 16 天

    [LV.4]偶尔看看III

    0

    主题

    1万

    回帖

    7618

    积分

    二级逆天

    积分
    7618

    终身成就奖特殊贡献奖原创先锋奖优秀斑竹奖

    QQ
    发表于 2020-8-14 18:02:27 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    12

    主题

    7221

    回帖

    100

    积分

    游客

    积分
    100

    终身成就奖特殊贡献奖原创先锋奖优秀斑竹奖

    QQ
    发表于 2020-8-14 20:05:56 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    81

    主题

    1131

    回帖

    2376

    积分

    PADS20210122高级班

    积分
    2376

    终身成就奖

    发表于 2020-8-21 22:51:35 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    7

    主题

    156

    回帖

    0

    积分

    二级逆天

    积分
    0

    终身成就奖特殊贡献奖原创先锋奖

    发表于 2020-9-18 08:53:42 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    196

    主题

    3558

    回帖

    0

    积分

    二级逆天

    积分
    0

    终身成就奖特殊贡献奖原创先锋奖

    发表于 2020-10-23 13:09:33 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    196

    主题

    3558

    回帖

    0

    积分

    二级逆天

    积分
    0

    终身成就奖特殊贡献奖原创先锋奖

    发表于 2020-11-4 12:59:32 | 显示全部楼层
    回复

    使用道具 举报

  • TA的每日心情

    6 天前
  • 签到天数: 22 天

    [LV.4]偶尔看看III

    3

    主题

    2761

    回帖

    2808

    积分

    1元学习Allegro(1期)

    积分
    2808

    终身成就奖特殊贡献奖

    发表于 2021-7-25 09:00:30 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    17

    主题

    286

    回帖

    0

    积分

    Pads-230522高级班

    积分
    0

    终身成就奖

    发表于 2021-7-25 09:52:08 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    1

    主题

    6218

    回帖

    8730

    积分

    二级逆天

    积分
    8730

    终身成就奖特殊贡献奖原创先锋奖优秀斑竹奖

    QQ
    发表于 2022-2-6 09:04:19 | 显示全部楼层
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    论坛开启做任务可以
    额外奖励金币快速赚
    积分升级了


    Copyright ©2011-2024 NTpcb.com All Right Reserved.  Powered by Discuz! (NTpcb)

    本站信息均由会员发表,不代表NTpcb立场,如侵犯了您的权利请发帖投诉

    平平安安
    TOP
    快速回复 返回顶部 返回列表