在讨论结构体大小前,我们先看一个例子:
struct B
{
char a;//1个字节
int b;//4个字节
};//5个字节
int main()
{
printf("%d\n",sizeof(B));
return 0;
}
按照内置类型的字节大小,该结构体的大小共为5个字节。这里输出该结构体字节大小编译器给出的字节数为8个字节。这里存在内存对齐的问题。
内存对齐:在访问特定类型变量的时候, 不是从任意地址进行访问,需要在特定的内存地址进行访问,各种类型数据按照一定的规则在空间上排列,不是按照顺序排放。因为各个品台对存储空间的处理上有一定的区别,对某些特定的类型数据只能从某些特定的地址进行存取。如果不按照要求存放会在存取率上有一定的损失。
由于结构体大小的计算存在内存对齐问题,所以遵循以下两个原则:
1.前面所有成员的字节数能整除当前成员大小.解决单个变量
2.结构体的大小必须能整除单个最大类型的大小.解决数组
//结构体数组
struct F
{
int a;//4个字节
char b;//1个字节
};//总5+3个字节
struct F arr[2];
长度为2 的结构体数组,总字节数为8,数组第一个变量内存对齐,但是在后序访问中,存在内存不齐问题,起始地址为105,无法整除下一个变量的第一个整型变量大小。所以需要根据原则2,其大小必须能整除单个最大类型4,因此总的字节数应为4+1+‘3’=8,访问最后一个成员后,先向后移动3个字节数,再对下一个结构体数组变量成员进行存取。如下方图所示。
根据遵循的原则,对于刚开始的问题就有如下图所示的处理方式。在访问a一个字节结束后,向后偏移3个字节数,下一访问地址从104开始。总的字节大小为最后一个成员的偏移量加上最后一个成员的大小。这里的偏移量指的是结构体变量中成员的地址和结构体变量的地址的差。
//示例1
struct C
{
char a;//1+1
short b;//2
int c;//4
};//8
对于示例1单个变量,根据规则可以得出:第一个成员char大小为1,第二个short为2,不满足原则1,所以第一个成员"+1",第三个成员为4能被之前的总数整除。所以该结构体的大小为1+‘1’+2+4=8。
//示例2
struct E
{
char a;//1+3
int b;//4
long *c;//4+4
double d;//8
};//24
对于示例2 ,遵循以上的两个原则:该结构体的大小为24个字节。
以上是结构体大小计算的理解。