今天我们来讲讲结构体的大小如何来计算
其中涉及到一个结构体中的热门考点:结构体内存对齐
话不多说,开始学习!
要想计算结构体的大小,首先要了解结构体的对齐规则。
目录
结构体内存对齐规则
举例
为什么存在内存对齐?
如何修改默认对齐数?
结构体内存对齐规则
1、第一个成员在与结构体变量偏移量为0的地址处。
2、其他成员变量要对齐到对齐数的整数倍地址处。
对齐数=编译器默认对齐数与该成员大小的较小值。
VS中默认的值为8,Linux gcc无默认对齐数,其对齐数就是成员变量自身大小。
3、结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
4、如果嵌套了结构体的情况,嵌套的结构体对齐到自己的成员中最大对齐数的整数倍处,结构 体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
举例
struct s1
{
char c1;
int i;
char c2;
};
如图,内存中有一块空间放的是结构体s1,
(1)对于第一个成员变量c1,它在与结构体变量偏移量为0的地址处(也就是图中的0),因为c1的类型是char(占一个字节),所以图中灰色的格子放的就是c1
(2)接着,对于第二个成员变量 i 它的类型是int,为四个字节,又因为在VS中默认对齐数是8字节,4<8,所以,变量 i 的对齐数为4。因为要放到对齐数整数倍位置,所以 i 应该放在偏移量为4的位置,图中黄色格子放的就是 i 。
(3)再然后,对于第三个成员变量c2,它的类型是char,大小为1字节,1<8, 所以c2的对齐数是1。因为要放到对齐数整数倍位置,所以c2可以放在偏移量为8的位置,图中红色格子放的是c2.
(4)最后,因为结构体总大小为最大对齐数的整数倍。前面我们已知c1对齐数=1,i 对齐数=4,c2对齐数=1,所以,结构体的最大对齐数为4,所以结构体的最终大小应该对齐4的整数倍位置,即图中12的位置,所以,整个结构体大小为12.
结构体嵌套问题
struct s2
{
char c1;
struct s1 s1;
double d;
}
若出现结构体嵌套问题,如上图
需先计算struct s1的最大对齐数,由第一个案例可知,结构体s1的最大对齐数是4,所以struct s1对齐到4的整数倍位置即可.
为什么存在内存对齐?
大部分参考资料是这么说的:
1、平台原因(移植原因)
不是所有平台都能访问任意地址上的任意数据的,某些硬件平台只能在某些地址取某些特定类型的数据,否则抛出硬件异常。
2、性能原因:
数据结构(尤其是栈)应该尽可能地在自然对齐边界上对齐。
原因在于,为了访问未对齐的内存,处理器需要做两次内存访问;而对齐的内存仅需要访问一次。
总体来说:结构体内存对齐是拿空间换时间的做法。
在设计结构体的时候,让占用空间小的成员尽量集中在一起,可以既满足对集,又节省空间。
如何修改默认对齐数?
结构体在对齐方式不合适的时候,我们可以修改默认对齐数。
如:
#pragma pack(4)//更改默认对齐数为4
struct s1
{
char c1;
int i;
char c2;
};
#pragma pack()//还原为默认