结构体及其偏移量的计算

结构体的定义

不同类型的结合称为 结构体,相当于数组。但数组中的每个元素都是同一个类型,但结构体中的成员可以是不同类型。

同类型的两个结构体变量可以直接赋值,相当于 浅拷贝 memcpy()

1
2
3
4
5
6
struct 结构的类型名称
{
类型名1 成员名1;
....
类型名2 成员名2;
}
  • 结构体的定义只是类型的定义,不占内存的空间。

  • 只有在描述具体的结构体实体时,才会占用内存。

  • 结构体的内存占用是线性的,但可能不是连续的。

结构体的偏移地址 Offset

结构体的 . 运算访问结构体成员变量,相当于对结构体进行偏移地址的计算

结构体的首个成员的偏移地址 offset 为0

VC6Struct member alignment 中设置 对齐地址,默认为 8byte

如果编译器为 VS2013 则在 属性类容-C/C++-代码生成-结构体成员对齐 中设置

计算偏移地址

计算公式

设编译选项设定的对齐值为 Zp(默认8byte),每个结构体成员的偏移量为 Offset

必须满足 (上一个成员的offset + 上一个成员的size) % min(sizeof(member type),Zp) == 0

如果为嵌套结构体,结构体名为 StruAli1Offset % min(StruAli1 ,Zp) == 0

结构体StruAli1 的对齐值为 *max(sizeof(member1 type),sizeof(member2 type)…sizeof(memberNtype)) *

member1,member2,member3 为 StruAli1 的成员

如果 offset + size 不满足 取模运算 == 0

offset + size +1 直到可以 == 0

计算过程

  1. 定义结构体

​ 设置对齐地址为 4

1
2
3
4
5
6
7
8
struct Person
{
char szName[6];
int nAge;
float fHeight;
double dblWeight;
char cGender; //Male Female Unknow Other
}
  1. 计算偏移量
  • 计算首个成员 szName 的偏移量为 0 ,大小为 6

  • 计算成员 nAge 的偏移量: ( 0(szName的偏移量) + 6(szName的大小)) % min(sizeof(nAge) , 4(对齐地址)) == 6 % min(4, 4)

    6 % 4 ! = 0,则6 + 1 % 4

    7 % 4 != 0,则7 + 1 % 4 == 0

    所以成员 nAge 的偏移量为 8

  • 计算成员 fHeight 的 偏移量:( 8(nAge的偏移量) + 4(nAge的大小)) % min (sizeof(float) , 4) == 12 % min(4, 4)

    12 % 4 == 0

    所以成员 fHeight 的偏移量为 12

  • 计算 dblWeight 的偏移量:(12+4) % min(8, 4) == 16 % 4 == 0

    成员 dblWeight 的偏移量为 16

  • 计算 cGender 的偏移量:(16+8) % min(1, 8) == 24 % 1 == 0

    成员 cGender 的偏移量为 24

成员 偏移量 offset 大小 size
szName[6] 0 6
nAge 8 4
fHeight 12 4
dblWeight 16 8
cGender 24 1

计算结构体的大小sizeof(struct)

计算公式

Zp 为设定的对齐值为 4

MaxValue= max(sizeof(member1 type),sizeof(member2 type)……sizeof(member3 type))

MinValue = min(MaxValue,Zp)

Size % MinValue == 0

Size 为结构体最后一个成员的偏移量 + 最后一个成员的大小

如果 Size % MinValue != 0 则Size ++

最终的 Size 为结构体的大小

计算过程

例如 Person 结构体

MaxValue = max(sizeof(szName), sizeof(nAge), sizeof(fHeight), sizeof(dblWeight), sizeof(cGender)) == sizeof(dblWeight) == 8

MinValue = min(8,4) == 4

Size % MinValue == (24 + 1) % 4 != 0

Size ++

(25 + 1) % 4 != 0

Size ++

(26+ 1) % 4 != 0

Size ++

(27+ 1) % 4 == 0

所以在对齐值为 4 时,Person 的大小为 28