详解结构体内存对齐 |
您所在的位置:网站首页 › 内存计算定义及分类 › 详解结构体内存对齐 |
目录 前言 一、内存大小的计算 1.规则 2.练习 二、为什么要有内存对齐 1.移植原因 2.性能原因 三、修改默认对齐数 总结 前言本文针对结构体大小的计算进行深度剖析。结构体的大小要遵守内存对齐,在绝大数情况下,会浪费空间。但是有其的价值,仔细阅读本文,将会对内存对齐有深刻的认识,知其本因。 一、内存大小的计算 1.规则1. 第一个成员在与结构体变量偏移量为0的地址处 2. 从第二个成员开始,以后每个成员都要对齐到某个对齐数的整数倍位置 这个对齐数是自身成员大小和默认成员对齐数的较小值 备注: vs环境下默认成员对齐数是8 3.当成员全部放入后,结构体的总大小必须是所有成员对齐数中最大对齐数的整数倍 4.如果嵌套了结构体,嵌套的结构体成员要对齐到自己成员的最大对齐数的整数倍处。 整个结构体的大小,必须是最大对齐数的整数倍,最大对齐数包含嵌套结构体的对齐数。 以上这是最常见的计算,下面我将通过就几道题帮大家理解 2.练习1)计算大小 struct S1 { char c1; int i; char c2; };答案:12 详解: 以32位系统为例子 第一个char 类型c1 大小为1,放在偏移量为0的位置上 第二个元素为int 大小为4,要放在某个对齐数上,这个对齐数是自身4和默认对齐数8的较小值 4 .所以i要放在4的倍数上,离i最近的位置偏移量为4,所以之前浪费了三个空间 第三个元素c2,要放在自身大小1和默认对齐数8的较小值1的倍数上,由于i以及占用了7的位置,所以c2要放在偏移量为8的位置上,总计大小为1+3+4+1=9 最后计算总结构体的大小,成员最大对齐数是4 ,但是上述分析为9,不满足4的倍数,就要浪费3个空间,到12上。 下面就通过一张图解来帮助理解 2)、计算大小 struct S2 { char c1; char c2; int i; };答案:8 题解: 第一成员c1在偏移量为0处。 c2对齐到在自身大小1与默认对齐数8的较小值1的整数倍处,就是在1处。 i对齐到4的倍数处,这里就是4,之前浪费了2个空间 大小是1+1+2+4=8 是成员最大对齐数4的整数倍,所以结构体大小就是8 3)、计算大小 struct S3 { double d; char c; int i; }; printf("%d\n", sizeof(struct S3));答案:16 题解: d在偏移量为0处,往后占8个空间 c要对齐到1的倍数处,本题为9 i要对齐到4的倍数处,本题要对齐到12,之前浪费3个空间,之后往后占4个空间 总大小8+1+3+4=16 是成员最大对齐数8的整数倍,所以结构体大小为16 4)、结构体嵌套 struct S4 { char c1; struct S3 s3; double d; }; printf("%d\n", sizeof(struct S4));题解: c1在偏移量为0处,往后占用一个空间 s3要对齐到某个对齐数的整数倍数处。由于s3是结构体,结构体成员的对齐数是自己的最大对齐数,也就是s3中d的对齐数,所以要对齐到8处。往后占用16个空间 d要对齐到8的整数倍数处,也就是24,往后占用8空间 总大小1+7(浪费空间)+16+8=32,是最大对齐数8的整数倍,所以结构体大小为32 答案:32 不是所有的平台都能访问任意空间的数据,所有就要存在一个规定,保证有效移植 2.性能原因在32位上,硬件在(栈区)访问一次是4字节,存在内存对齐,在访问相同数据时能减少访问次数。以空间换时间。 所以在设计结构体时,尽量让内存小的成员放在一起 就比如题目1和题目2,二者的成员变量相同,但是顺序不同,占用的空间大小不同 所以: 结构体内存对齐的意义就是以空间换时间,设计时,尽量将小成员放一起。 三、修改默认对齐数#pragma pack( 要修改的数) 修改默认对齐数,一般都是2的n次方 总结结构体内存对齐是常考点。在进行对齐时,一般总会浪费掉空间,但是却有利于移植,有助于提升效率。内存对齐掌握上述的4条规则,便可游刃有余。 我是凡凡,感谢大家阅读! |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |