一文带你详细了解【结构体中的内存对齐】,让你快速掌握计算结构体的大小!

发布于:2022-12-13 ⋅ 阅读:(498) ⋅ 点赞:(0)

0. 先看一道题目

struct A
{
	int a;
	short b;
	int c;
	char d;
};

小伙伴一看,肯定心想这不是so easy吗,sizeof(A),我们肯定是认为4+2+4+1=11,所以sizeof(A)=11!
在这里插入图片描述

哈哈,那么答案是不是这样呢?我们来分析一波!

1. 结构体中的内存对齐[vs2019环境下]

结构体在内存中存储时,并不是按照上面我们所想的那样,一个一个存放进去的!那么它具体时怎么样的呢?我们来分4个步骤来分析!

1.1 第一步

第一个成员在与结构体变量偏移量为0的地址处。

在这里插入图片描述

1.2 第二步

从第二个成员开始,要对齐到某个【对齐数】的整数倍的偏移处。
对齐数:结构体成员自身大小和默认对齐数中的较小值

在这里插入图片描述
紧接着第三个成员
在这里插入图片描述
最后一个成员
在这里插入图片描述

1.3 第三步

结构体的总大小必须是最大对齐数的整数倍!(每个结构体成员都有一个对齐数,其中最大的对齐数就是最大对齐数)

从图中可以看出结构体此时总大小为13,此时并不是最大对齐数4的整数倍,所以应该扩展到16,所以最终sizeof(A)为16!

1.4 第四步【如果存在嵌套结构体的情况下】

如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

在这里插入图片描述

先分析B的大小
在这里插入图片描述

在分析A的大小
在这里插入图片描述

2. 为什么要存在内存对齐呢?

2.1 平台原因

不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。

2.2 性能原因

数据结构(尤其是栈)应该尽可能地在自然边界上对齐。
原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;
而对齐的内存访问仅需要一次访问。

那在设计结构体的时候,我们既要满足对齐,又要节省空间,如何做到:
让占用空间小的成员尽量集中在一起!
例如:

struct S2
{
 char c1;
 char c2;
 int i;
};

3.修改默认对齐数

我们可以通过 pragma pack() 来修改默认对齐数

#include <stdio.h>
#pragma pack(8)//设置默认对齐数为8
struct S1
{
 char c1;
 int i;
 char c2;
};
#pragma pack()//取消设置的默认对齐数,还原为默认

结构在对齐方式不合适的时候,我么可以自己更改默认对齐数。

4. 结束语

看到这里,小伙伴应该明白了为什么一开始的结果和你想的不一样了把!


网站公告

今日签到

点亮在社区的每一天
去签到