C代码中定义的结构体是一块连续内存,各成员按照定义的顺序依次在其中存放。编译器在完成语法分析后,需要计算它的大小,然后才能正确地为结构体分配空间。为了让结构体的所有成员都能正确、快速地访问,需要字节对齐。
字节对齐体现为:
在成员之间可能增加补齐字节,以调整每个成员的偏移;
结构体末尾,也可能增加补充字节。所有补齐字节计入结构体的大小。
我们通过以下几个例子认识结构体大小知识:
1、
struct B
{
char a;//1+3
int b;//4
}; //8
printf("%d\n",sizeof(struct B));
因为考虑内存对齐,此时struct B 的大小为8。
2、
struct C
{
char a;//1+1
short b;//2
int c;//4
};//8
struct D
{
char a;//1+3
int b;//4
short c;//2
};//10+2
通过结构体C和结构体D看出,不同数据类型存放顺序不同,结构体大小不同。
3、
struct A
{
int a;//4
char b;//1
};//5+3
105不能被4整除,在其末尾添加填充3字节。注意与结构体B区别。
同等情况案例:
struct H
{
char a;//1+3
int b;//4
double c;//8
int *d;//4
};//20+4
4、
struct II
{
int a;
char b;
};
struct I
{
float x;//4
//struct II y;//8
double y;
};//12 单个最大类型
结构体总的大小要是其成员中最大size的整数倍,如果不是编译器会在其末尾添加填充字节
总结:
- 结构体第一个成员的地址和结构体的首地址相同
- 结构体每个成员地址相对于结构体首地址的偏移量(offset)是该成员大小的整数倍,如果不是则编译器会在成员之间添加填充字节(internal adding)。
- 结构体总的大小要是其成员中最大size的整数倍,如果不是编译器会在其末尾添加填充字节。