很多初学者对于结构体长度的计算是毫无头绪,下面的计算方法是我个人简介,仅供参考。
- C语言的编译过程是从上到下的。
- 结构体某成员的地址偏移量必须为该成员的整数倍,如果不是整数倍,则前面成员变量需要填充。
- 结构体最后一个成员所占字节的长度=max(所有的成员长度)。
下面以一例子来解说:
struct abc{ char e; int i; char f; int b; char g; double a; char h; struct abc *c; float d; }k; |
首先说明一下,我的电脑是64位的,char占1个字节、int占4个字节、float占4个字节、指针变量占8个字节(因为是64位计算机)、double占8个字节。
- 依据条件1(即编译过程是从上到下编译的),变量e的地址偏移为0,是char类型长度的整数倍;
- 如果e没有填充,那么变量i的偏移地址为1,由于int类型长度为4,显然1不是4的整数倍,故变量e需要填充3个字节,使得int i变量的偏移地址为4(为int类型长度的整数倍);
- char f变量的偏移地址为8,是char类型长度的整数倍;
- 如果f变量没有填充,那么int b的偏移为9,不是4的整数倍。故而char f需要填充3位,使得int b的偏移为12。
- char g变量的偏移为16,是char类型长度的整数倍;
- 如果char g没有填充,那么double a的偏移地址为17,不是double类型长度(8字节长)的整数倍,故而char g需要填充7位。
- 如果double a没有填充,char h的偏移地址为32,显然是char类型长度的整数倍
- 如果char h没有填充,那么c的偏移地址为33,不是指针长度(8字节,如果是32位计算机则为4字节)的整数倍。故而char h需要填充7字节。
- 如果c没有填充,那么float d变量的偏移地址为48,是float类型长度(4字节长)的整数倍。由于最后一个成员的数据长度应该为结构体最长成员的长度。故而整个结构体长度为56个字节。
下面是程序验证的结果:
结构体成员 | 起始地址地址 | 成员长度 |
k.e | 2293264 | 4 |
k.i | 2293268 | 4 |
k.f | 2293272 | 4 |
k.b | 2293276 | 4 |
k.g | 2293280 | 8 |
k.a | 2293288 | 8 |
k.h | 2293296 | 8 |
k.c | 2293304 | 8 |
k.d | 2293312 | 8 |
如果上面结构体变量按照下面顺序定义成员,结构体存储所占内存将大大减小:
struct abc{ char e; char f; char g; char h; int i; int b; float d; double a; struct abc *c; }k; |
大家算一算这种定义方法所占内存空间的大小。答案:32个字节