结构体嵌套大小和指定对齐数时的大小计算
作者:互联网
1.一般结构体大小计算原则
一,结构体变量的首地址,必须是结构体 “最宽基本类型成员” 大小的整数倍。
二,结构体每个成员相对于结构体首地址的偏移量,都是该成员的整数倍。
三,结构体的总大小,为结构体 “最宽基本类型成员” (将嵌套结构体里的基本类型也算上,得出的最宽基本类型) 大小的整数倍。
1、简单结构体
struct s1{
char ch1;
char ch2;
int i;
};
这个结构体的大小容易计算,满足后两个原则即可,为8。
struct s2{
char ch1;
int i;
char ch2;
};
这个结构体大小是12,为什么呢?仔细看看后两个原则,要满足偏移量是成员的整数倍,ch1偏移量是0,i的偏移量不可能是1,因为1不是i大小4的倍数,所以i的偏移量是4,ch2的偏移量就变为了8,加ch2是9,要满足结构体大小是成员大小整数倍,就是12。
2、成员包含数组的结构体
struct s3{
char ch;
int i;
char str[10];
};
这个结构体的大小是20,先看前两个成员,大小是8,毋庸置疑,这个char类型的数组,只需要把它看做十个char连在一起即可,加起来就是18,再满足结构体大小为成员整数倍,所以大小就是20。
2.嵌套结构体大小计算原则
对于嵌套的结构体,需要将其展开。对结构体求sizeof时,上述两种原则变为:
展开后的结构体的第一个成员的偏移量应当是被展开的结构体中最大的成员的整数倍。
结构体大小必须是所有成员大小的整数倍,这里所有成员计算的是展开后的成员,而不是将嵌套的结构体当做一个整体。
解释
对于原则1:
struct strA
{
short i;
struct strB
{
char c;
int j;
} ss;
int k;
} ;
对于以上例子strA的成员ss.c的大小是4,而不是2。因为其对齐原则依据ss.j确定。整个结构体的大小是16
对于原则2:
#include <iostream>
using namespace std;
struct strA
{
short i;
struct strB
{
char c;
int j;
} ss;
char a;
char b;
char c;
char d;
char e;
char f;
};
int main()
{
cout << sizeof(strA)<<endl;
system("pause");
}
sizeof(strA)=20,不是8的整数倍(结构体strB单独计算占用空间为8),这说明在计算sizeof(strA)时,将嵌套的结构体ss展开了,这样strA中最大的成员为ss.j,占用4个字节,20为4的整数倍。(如果将ss当做一个整体,结果应该是24)
对于结构体中有数组的特殊情况:其sizeof应当和处理嵌套结构体一样,将其展开,如下例子:
struct strA
{
float a;
char b;
int c[3];
};
其值为20
float占4个字节,到char b时偏移量为4,b占一个字节,到int c[3]时偏移量为5,扩展为int的整数倍,而非int c[3]的整数倍,这样偏移量变为8,而不是12。结果是8+12=20,是最大成员float或int的大小的整数倍。
3.指定对齐数时结构体大小计算原则
一,结构体变量的首地址,必须是 min(“结构体最宽基本类型成员”, 指定对齐方式) 大小的整数倍。
二,结构体每个成员相对于结构体首地址的偏移量,都是 min(该成员, 指定对齐方式)大小的整数倍。
三,结构体的总大小,为min( 结构体 “最宽基本类型成员” (将嵌套结构体里的基本类型也算上,得出的最宽基本类型), 指定对齐方式) 大小的整数倍。
(1)对齐值小于最大类型成员值
#pragma pack(4) //指定向4对齐 最大是8
struct s6{
char ch;
int i;
float f;
double d;
};
如果我们没有指定对齐值,这个结构体大小是24,我们指定向4对齐,所以大小是4的倍数,所以结构体大小是20。
(2)对齐值大于最大类型成员值
#pragma pack(10)
struct s7{
char ch;
int i;
float f;
double d;
};
我们指定的对齐值是10,最大为8,是否就向10对齐?不是,当指定对齐值大于自身对齐值时,向自身对其值对齐,大小是24.
总的来说,向指定对齐值和自身对齐值中较小的那个值对齐。
标签:数时,int,整数倍,char,嵌套,大小,对齐,结构 来源: https://blog.csdn.net/tonglin12138/article/details/120809461