论坛风格切换切换到宽版
发帖 回复
返回列表  提醒:不能用迅雷等P2P下载,否则下载失败标(二级)的板块,需二级才能下载,没二级不要购买,下载不了
  • 987阅读
  • 11回复

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

上一主题 下一主题
离线ajtdnta
 

性别:
人妖
发帖
9
金币
9
提示:会员销售的附件,下载积分 = 版块积分 + 销售积分       只看楼主 倒序阅读 使用道具 0楼 发表于: 2020-08-14
写的很辛苦,都是一字一字敲出来的,希望能帮助到大家。 =TR,~8Z|  
如果有不对的地方,欢迎大家交流。 >#+IaKL7  
前提条件:确认所有基本数据类型分别占用多少个字节。(这个不完全跟平台一致,不要简单地说8位机,16位机, 32位机, 64机,它还跟编译器本身密切相关) ^ 4%Zvl  
这里就拿32位平台下,并且sizeof(char)=1, sizeof(short)=2, sizeof(int)=4 sizeof(long)=8的情况来说明。(听到32位就理所当然地说是按4字节对齐也是致命的。 ) %}2@rLP  
几个注意事项: 3E}EBJLsZ  
1.  当前结构体成员本身需要几个字节来储存。(以上都有说明,看成员类型就知道了) ! #wdVe_(  
2.  下一个结构成员所需要的空间。(如果下一个成员占用字节较大,当前和往后都按大的字节数来对齐) DaNW~rd{  
3.  当前结构体成员当中,占用最多的成员是多少个字节。(这里的“当前结构体”是指从第一个成员到正在分析的那个成员为止的结构体) [fu!AIQs  
4.  正在分析的成员按新的对齐来处理后,需要填充的字节是否能够存下一个成员。如果可以,下一个成员有定义和无定义都不会对总占用 - ~O'vLG  
字节数产生影响。 ]j>i.5  
(在分析结构所占字节数时,请按顺序进行) NV4g~+n  
下面举个例子 S)He$B$pp  
typedef struct 6]Q3Yz^h  
{ Z?i /r5F  
    char    a; wHz?#MW 3L  
    short   b; nW\(IkX\  
    int       c; F=G{)*Ih  
    long    d; 5p?!ni9  
    char    e; 4X NxI1w)  
}test_t; g. %  
请问以上结构体在当前约束条件下,占用多少字节的内存空间? ]O:M$ $  
分析: 3L-^<'~-k;  
从第一个成员开始: Bz8 &R|~>"  
char a;(1) 它占用一个字节, (2)它的下一个成员 short b; 需要占用2个字节 (3) 到short b;为止占用字节最多的是2字节的short b; 好,到此为止,结构会按当前占用字节数最大的成员所占用的字节数来对齐,也就是按2字节对齐,所以char a; short b;一共要占用4个字节 。 rl:KJ\*D  
现在开始分析int c; 4yMW^:@  
毫无疑问到此为止占8个字节。 b hjZ7=  
同理, long d; 加入后占16字节, 但到此为止,结构体中占字节最多的是8字节的long, 所以后面增加的成员只要是在8字节以内,都得占 1;u4X`8  
8字节 ,哪怕char e;只占了一个字节,因为在此之后,要按8字节来对齐了。 Hv#q:R8  
所以sizeof(test_t) = 2+2+4+8+8=24字节。 D)='8jV7  
 ]^"k8v/  
下面来一题,巩固一下: uK*Nu^  
typedef struct eR']#Q46{T  
  { KB{RU'?f|  
    char  a; //2 (本来占1字,因为后面的b要2字节对齐,所以要填充一个字节) `ia %)@  
    short b; //2   (当前占四字节,后面的c也占四字节,刚好对齐,所以不用填充,就占2字节)   1S%k  
    int     c; //4   (后面的d, 只占一个字节, 所以c不用填充, 但往后要按4字节对齐了)   3bC yTZk  
    char  d  //8  (如果没有后面的long e, 它是按4字节对齐至少要占用4字节,但后面来个long e, 需要填充7字节,所以d 要占用8个字节) {I%y;Aab8  
    long  e; //8 bv?0.{Z  
    char  f[9];//16 OKuD"   
} test_t; k D~uGA  
sizeof(test_t) = 2+2+4+8+8+16=40; e xR^/|BR  
另外,如果用了#pragam pack(n)   //n为 >=0 且为2的较小次方的整数, 或者不写 "5DJu ~  
那么对齐方式是按设定的来。 n1(?|aJ#1  
比如 \Z)1 ?fq  
#pragma pack(1) Qqs"?Z,P  
typedef struct 5#:pT  
{ 1r`i]1<H  
    char  a; q/@dR{-  
    short b; mAqD jRV1  
    int     c; _[Gb)/@mM  
    char  d; (4~WWU (iT  
    long   e; hsce:TB  
    char   f[9]; /dHs &SU,  
} test_t; =7[)'  
#pragma pack() 5P^U_  
它按1字节对齐,只占25字节。 sn\;bq  
如果上述结构体,指定pack(2)那么它就只占28字节。 <3 @}Lj  
}#9(Mul  
总结起来就是: 0TE@xqW  
1.  当前成员占多少字节 yM$J52#d#  
2.  下个成员占多少字节 I/u9RmbU  
3.  当前和往后按多少字节对齐 DMgBcP  
4.  新的对齐方式下,当前成员填充的字节数够不够容得下下一个成员。 1 0N,?a  
。。。。 go|>o5!g  
1.  当前成员占多少字节 tFU;SBt8Ki  
2.  下个成员占多少字节 vgPUIxB@  
3.  当前和往后按多少字节对齐 :uCdq`SaQl  
4.  新的对齐方式下,当前成员填充的字节数够不够容得下下一个成员。 p,#6 @*  
。。。。 i&tsYnP2  
1.  当前成员占多少字节 i*tv,f.(  
2.  下个成员占多少字节 6TFo|z!C  
3.  当前和往后按多少字节对齐 z4O o@3$\R  
4.  新的对齐方式下,当前成员填充的字节数够不够容得下下一个成员。 o\4t4}z~'f  
这是一个递归的过程,用好它去分析每一个成员就行了。 9 pKm*n&  


评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

一般

差劲
离线mj8abcd

性别:
帅哥
发帖
10527
金币
4759
提示:会员销售的附件,下载积分 = 版块积分 + 销售积分       只看该作者 1楼 发表于: 2020-08-14
  


离线地沟油

性别:
人妖
发帖
7241
金币
4361
提示:会员销售的附件,下载积分 = 版块积分 + 销售积分       只看该作者 2楼 发表于: 2020-08-14
        


离线墙头草

性别:
人妖
发帖
1213
金币
2022
提示:会员销售的附件,下载积分 = 版块积分 + 销售积分       只看该作者 3楼 发表于: 2020-08-21


离线sunbonnet

性别:
人妖
发帖
163
金币
127
提示:会员销售的附件,下载积分 = 版块积分 + 销售积分       只看该作者 4楼 发表于: 2020-09-18
    


离线逆天pads

性别:
帅哥
发帖
3796
金币
1200
提示:会员销售的附件,下载积分 = 版块积分 + 销售积分       只看该作者 5楼 发表于: 2020-10-23


离线逆天pads

性别:
帅哥
发帖
3796
金币
1200
提示:会员销售的附件,下载积分 = 版块积分 + 销售积分       只看该作者 6楼 发表于: 2020-11-04


离线zhhuxx

性别:
人妖
发帖
2715
金币
1798
提示:会员销售的附件,下载积分 = 版块积分 + 销售积分       只看该作者 7楼 发表于: 2021-07-25
  


离线17369281225

性别:
人妖
发帖
303
金币
806
提示:会员销售的附件,下载积分 = 版块积分 + 销售积分       只看该作者 8楼 发表于: 2021-07-25


离线sun5304

性别:
帅哥
发帖
6244
金币
8073
提示:会员销售的附件,下载积分 = 版块积分 + 销售积分       只看该作者 9楼 发表于: 2022-02-06
  


离线aliswang

性别:
人妖
发帖
527
金币
493
提示:会员销售的附件,下载积分 = 版块积分 + 销售积分       只看该作者 10楼 发表于: 2022-02-11
6'6@VB  


在线haohao96

性别:
人妖
发帖
158
金币
449
提示:会员销售的附件,下载积分 = 版块积分 + 销售积分       只看该作者 11楼 发表于: 2022-07-14
谢谢楼主分享!


快速回复
限150 字节
 
上一个 下一个