解析C语言中结构体struct的对齐问题
2019/7/10 22:59:27
本文主要是介绍解析C语言中结构体struct的对齐问题,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
首先看一下结构体对齐的三个概念值:
数据类型的默认对齐值(自身对齐):
1.基本数据类型:为指定平台上基本类型的长度。如在32位机器中,char对齐值为1,short为2,int,float为4,double为8;
结构体:其数据成员中默认对齐值最大的那个值。
2.指定对齐值:#pragma pack (value)时的指定对齐值value。
3.数据类型的有效对齐值:默认对齐值和指定对齐值中小的那个值。
有了这些值,我们就可以很方便的来讨论具体数据结构的成员和其自身的对齐方式。有效对齐值N是最终用来决定数据存放地址方式的值,最重要。有效对齐N,就是表示“对齐在N上”,也就是说该数据的“偏移量%N=0”。而数据结构中的数据变量都是按定义的先后顺序来排放的。第一个数据变量的起始地址就是数据结构的起始地址。结构体的成员变量要对齐排放(对于非对齐成员需要在其前面填充一些字节,保证其在对齐位置上),结构体本身也要根据自身的有效对齐值圆整(就是结构体总长度需要是结构体有效对齐值的整数倍)。
通过上面的分析,对结构体进行字节对齐,我们需要知道四个值:
- 指定对齐值:代码中指定的对齐值,记为packLen;
- 默认对齐值:结构体中每个数据成员及结构体本身都有默认对齐值,记为defaultLen;
- 成员偏移量:即相对于结构体起始位置的长度,记为offset;
- 成员长度:结构体中每个数据成员的长度(注结构体成员为补齐之后的长度),记为memberLen。
及两个规则:
1.对齐规则:
offset % vaildLen = 0,其中vaildLen为有效对齐值vaildLen = min(packLen, defaultLen);
2.填充规则:
如成员变量不遵守对齐规则,则需要对其补齐;在其前面填充一些字节保证该成员对齐。需填充的字节数记为padLen:
padLen = getPadLen(offset , defaultLen); int getPadLen(int offsetLen, int defaultLen) { int vaildLen = min(packLen,defaultLen); if(0 == vaildLen || 0 == offsetLen % vaildLen) { return 0; } return vaildLen - (offsetLen % vaildLen); }
结构体对齐算法思想:深度优先填充
先对齐内层结构体;
对每个数据成员计算其defaultLen、memberLen和offset;
再遍历每个数据成员时计算;
对于基本数据类型成员defaultLen=memberLen;对于结构体成员defaultLen等于它的所有成员的最大的memberLen;
遍历时对成员的memberLen进行累加,得到当前成员的offsetLen;
运用对齐及填充规则:在当前结构体成员前填充padLen个字节;
举例说明:
struct{ short a; short b; short c; }A; sizeof(A) = 6;
(vc6与gcc相同)
struct{ long a; short c; }A; sizeof(A) = 8;
(vc6与gcc相同), 它的内存分配为: a1 a2 a3 a4 , c1 c2 x x(a1为a的第一个字节,x为补齐字节,下同)
struct{ int a; char b; short c; }A; sizeof(A) = 8;
A的内存分配为:
a1 a2 a3 a4, b1 x c1 c2
struct{ char a; int b; short c; }A1; sizeof(A1) = 12;
(vc6与gcc相同)
A1的内存分配为:
a1 x x x, b1 b2 b3 b4, c1 c2 x x
下面是更复杂的情况,结构体作为成员
struct{ int a; doubl b; short c; }A; // sizeof(A) = 24 (vc6与gcc相同) struct{ char a,b; int c; double d; short e; struct A h; }B; sizeof(B) = 48 //(vc6与gcc相同)
A的内存分布:
a1 a2 a3 a4 x x x x, b1 b2 b3 b4 b5 b6 b7 b7, c1 c2 x x x x x x
B的内存分布:
a1 b1 x x, c1 c2 c3 c4 , d1 d2 d3 d4 d5 d6 d7 d8, e1 e2 x x x x
这篇关于解析C语言中结构体struct的对齐问题的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享
- 2024-11-23oss直传有什么好处?-icode9专业技术文章分享
- 2024-11-23如何将oss直传封装成一个组件在其他页面调用时都可以使用?-icode9专业技术文章分享
- 2024-11-23怎么使用laravel 11在代码里获取路由列表?-icode9专业技术文章分享
- 2024-11-22怎么实现ansible playbook 备份代码中命名包含时间戳功能?-icode9专业技术文章分享