C语言结构体大小;结构体嵌套结构体大小的计算方法分析
C语言结构体大小;结构体嵌套结构体大小的计算方法分析!
在了解结构体大小如何计算之前,我们首先得了解结构体的对齐规则:
第一个成员在与结构体变量偏移量为0的地址处;其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处;
对齐数 = 编译器默认的一个对齐数 与 该成员大小的 较小值
在vs环境下,默认值为8,而gcc没有默认对齐数,对齐数为环境自身大小;结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍;如果有嵌套了结构体的情况,其那套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
结构体的内存对齐就是拿 空间 来 换取 时间 的做法,以此来提升效率!
例如计算以下结构体的大小:
#include void test()
{struct S{int a;char b;short c;};printf("结构体S的大小为:%d \n",sizeof(struct S));}int main()
{test();return 0;
}};
其中:a本身大小为4个字节,b的大小为1个字节,c的大小为2个字节,加起来应该是7个字节,但是我们看一下运行结果:
为什么结果会是8呢?这就涉及到我们上面所说的结构体内存对齐的原则了,如图:
我们知道,在a,b,c三个变量中,a是第一个成员,从0处对齐(图中红色部分),b的大小为1,紧接着的4也是1的倍数,因此在4的位置可以直接对齐(图中橙色部分),c的大小为2,5并不是2的倍数,所以向后偏移一位到6的位置对齐(图中绿色部分)。又因为a是最大的为4个字节,所以结构体S中最大对齐数为4,因此,结构体总大小为最大对齐数4的整数倍,正好0 ~ 7是4的整数倍8个字节;
再来看以下结构体的情况:
#include void test()
{struct S{int a;char b;int c;short d;};printf("结构体S的大小为:%d \n",sizeof(struct S));
}int main()
{test();return 0;
}
其中,a的大小为4个字节,b的大小为1个字节,c的大小为4个字节,d的大小为2个字节;c为4个字节,d为2个字节,我们同样按照结构体大小对其的方式,来画出分析图:
从图中易知,a为第一个成员,在0处对齐,b大小为1,在4处对齐,c大小为4,5不是4的倍数,因此向后移动3位至8处对齐,d的大小为2,因此在紧接着c并且正好是2的倍数12处对齐,而整个结构体的大小为最大对齐数4的整数倍,14显然不是4的整数倍因此向后移动两位至16处,因此结构体大小为16;
运行结果验证:
下面我们再来看以下结构体嵌套结构体的情况:
#include void test()
{struct S{int a;char b;struct S* c;};printf("结构体S的大小为:%d \n",sizeof(struct S));
}int main()
{test();return 0;
}
当结构体中有嵌套了一个结构体的时候,嵌套的结构体对齐到自己的最大对齐数的整数倍处,我们观察代码易知,嵌套的结构体 ( S* c)中最大对齐数应为 S最大对齐数4;因此画图分析:
由图中易知,第一个成员a大小为4,从0处对齐,第二个成员b大小为1,从1的整数倍4紧接着a对齐,第三个成员是结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍处,嵌套的结构体 ( S* c)中最大对齐数应为 S最大对齐数4,而5并不是4的倍数,因此向后移动3为至8处对齐;
因此整个结构体的大小为最大对齐数4的倍数,而0~11大小为12,正好是4的倍数,因此本结构体的大小为12;
以下为运行结果验证: