结构体,公用体,枚举类型的sizeof

时间:2023-03-08 17:46:13
结构体,公用体,枚举类型的sizeof

1)枚举类enum型空间计算

enum只是定义了一个常量集合,里面没有“元素”,而枚举类型是当做int来存储的,所以枚举类型的sizeof值都为4

 enum color(red,pink,white,black)c;
void main()
{
cout<<sizeof(enum); //值为4
}

2)公用体union空间计算

公用体中的成员公用同一段内存,所以整个联合体的sizeof是所有成员中占用内存最大的成员的sizeof,联合体要考虑内存对齐,具体规则下面会讲

 union st{
char a[];
int b[];
}s;
void mian()
{
cout<<sizeof(s); //值为12
}

结果分析:sizeof(a)=9*1=9,sizeof(b)=2*4=8,选两者中最大的一个,即9,考虑内存对齐,整体空间长度要是公用体中长度最大的数据类型的整数倍,在这里是int占用空间的整数倍,比9大的且是4的整数倍的最小数是12

3)结构体struct空间计算

  • 首先空结构体的长度为1,之所以不是0,因为如果空结构体不占内存,则该结构的的变量将无法存取,且两个不同的空结构体无法区分
  • 非空结构体的计算遵循以下两个原则:

1.整体空间是结构体中占用空间最大的类型所占字节数的整数倍。特殊:在32位Linux+gcc环境下,若最大的类型所占字节数超过4,如double是8,则整体空间大小是4的整数倍即可

2.数据对齐原则-内存按结构体成员的先后顺序排列,当排到该成员变量时,其前面所有成员已经占用的空间大小必须是该成员类型大小的整数倍,如果不够,则前面的成员占用的空间要补齐,使之成为当前成员类型的整数倍。特殊:在Linux+gcc环境下,若当前成员类型字节数超过4,则前面所有成员已经占用的孔家大小是4的整数倍即可,不够则补齐

范例:

  • 结构体成员为普通数据类型成员:
 struct s{
char a;
double b;
int c;
char d;
};
void main()
{
cout<<sizeof(s); //值为24
}

结果分析:首先s中最大的类型为double,长度为8;顺序存放s中的成员,sizeof(a)=1,占用一个字节,下一个成员b是double类型,占用8个字节,根据原则2,a占用的内存补齐8的整数倍,即补齐到8个字节,b从第9个字节开始存放,此时共占用16个字节,下一个成员c是int类型,占用4个字节,16是4的整数倍,不用补齐,顺序存放c,此时占用空间来到20,d占用一个字节,20+1=21,根据原则1,整体空间大小需是double类型长度的整数倍,需将21补齐到24个字节

  • 结构体成员中存在其他结构体类型成员:

规则同上面基本相同,但计算时,设计到的倍数对齐,以子结构体中的最大成员类型占用的空间为基础,而不是将子结构体的整体空间为基础,具体如下:

1.整体空间是子结构体与父结构体中占用空间最大的类型所占字节数的整数倍。特殊:在32位Linux+gcc环境下,若最大的类型所占字节数超过4,如double是8,则整体空间大小是4的整数倍即可

2.数据对齐原则-内存按结构体成员的先后顺序排列,当排到子结构体成员时,其前面所有成员已经占用的空间大小必须是该子结构体成员中占用空间最大的类型大小的整数倍,如果不够,则前面的成员占用的空间要补齐,使之成为该类型大小的整数倍。特殊:在Linux+gcc环境下,若当前成员类型字节数超过4,则前面所有成员已经占用的孔家大小是4的整数倍即可,不够则补齐

  struct s1{
char c;
int i;
}; struct s2{
char c1;
s1 s;
char c2;
}; void mian()
{
cout<<sizeof(s1)<<endl; //
cout<<sizeof(s2)<<endl; //
}

结果分析:

s1:c占一个字节,i占4个字节,存放i之前将其补齐到4个字节,i从第5个字节开始存放,此时整体空间大小是8,恰好是4的整数倍

s2:c1占一个字节,下一个成员s,这里sizeof(s)虽然等于8,但计算时前面占用空间只要是s中最大类型的空间长度的整数倍即可,s中最大类型是int,所以c1占用的内存补齐到4,然后存放s(注意这里存放的是s,而不是int占用的字节),已计算出sizeof(s)=8,此时整体空间来到12,c2占一个字节,12+1=13,根据原则1,整体空间大小需是父结构体和子结构体重最大类型长度int的整数倍,最近的是16.