总结一下结构体大小问题
1. 一般结构体大小
对于一般的结构体大小遵循两条原则:
- 结构体成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍)
- 结构体大小必须是所有成员大小的整数倍
解释
struct strA
{
int a;
char b;
double c;
short d;
};
1)
sizeof(a)=4,a的偏移地址式4的倍数,从0开始,3结束;
sizeof(b)=1,b的偏移地址式1的倍数,从4开始,4结束;
sizeof(c)=8,c的偏移地址式8的倍数,从8开始,15结束;
sizeof(d)=2,d的偏移地址式2的倍数,从16开始,17结束;
2)
由于结构体的最大元素是c,为8,8是其他元素的倍数;因为常见变量是成倍数关系,所以第二条原则也可以说明为:结构体大小是最大元素的倍数;
所以结构体的大小应该是8的倍数,取24;
2. 嵌套结构体大小
对于嵌套的结构体,需要将其展开。对结构体求sizeof时,上述两种原则变为:
- 展开后的结构体的第一个成员的偏移量应当是被展开的结构体中最大的成员的整数倍。
- 结构体大小必须是所有成员大小的整数倍,这里所有成员计算的是展开后的成员,而不是将嵌套的结构体当做一个整体。
解释
对于原则1:
struct strA
{
short i;
struct strB
{
char c;
int j;
} ss;
int k;
} ;
对于以上例子strA的成员ss.c的大小是4,而不是2。因为其对齐原则依据ss.j确定。整个结构体的大小是16
补充:对于分开的情况也是一样处理
#include <iostream>
using namespace std;
struct strB
{
char c;
double j;
};
struct strA
{
short i;
strB j;
int k;
};
int main()
{
cout << sizeof(strA)<<endl;
system("pause");
}
对于原则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的大小的整数倍。
如何给结构体变量分配空间由编译器决定,以上情况针对的是Linux下的gcc。在Windows下的VC平台也是这样,至于其他平台,可能会有不同的处理。
以上有参考网络。个人水平难免有错,谢谢告知。