四个概念
1、基本数据类型的自身对齐值
2、自定义类型的自身对齐值
3、程序的指定对齐值 #Pragma pack()
4、程序的有效对齐值:较小的
内存对齐的作用:
假如没有内存对齐机制,数据可以任意存放,现在一个int变量存放在从地址1开始的联系四个字节地址中,该处理器去取数据时,要先从0地址开始读取第一个4字节块,剔除不想要的字节(0地址),然后从地址4开始读取下一个4字节块,同样剔除不要的数据(5,6,7地址),最后留下的两块数据合并放入寄存器.这就很麻烦而且很耗费时间
现在有了内存对齐的,int类型数据只能存放在按照对齐规则的内存中,比如说0地址开始的内存。那么现在该处理器在取数据时一次性就能将数据读出来了,而且不需要做额外的操作,提高了效率。
内存对齐的原理:
我们首先知道,char是一个字节,int是四个字节,double是八个字节。
那我们定义结构体的时候,包含char,int,double三个类型,那结构体的字节是多少?
#include<bits/stdc++.h>
using namespace std;
typedef struct Test
{
char a;
double b;
int c;
}Test;
int main()
{
printf("size = %d\n",sizeof(Test));
system("pause");
return 0;
}
如果是简单的把char,int,double相加的话,就没有内存对齐,我们先看看其占的字节大小
这是怎么算的?我们来看看内存对齐的规则:
1、找出每个成员变量的大小将其与默认对齐值相比较,取其较小值为该成员变量的对齐值。
2、根据每个成员对应的对齐数画出它们在内存中的相对位置。
3、通过最大对齐数决定最终该结构体的大小
我们来计算一下上面程序的结构体的内存值:
char 占一个字节,存在于第1个字节, double占八个字节,存在于第八个字节(整数倍)
int占4个字节,存在于第20个字节(整数倍)
第1个字节是char,然后第2到第七个字节是空的浪费的,然后第八到第十六是double占的,int则是第二十到第二十四,所以一共占24个字节。
如果换个顺序呢?把char,double和int换个顺序
typedef struct Test
{
char a;
int c;
double b;
}Test;
int main()
{
printf("size = %d\n",sizeof(Test));
system("pause");
return 0;
}
我们可以得出一个结论,把变量由字节从小到大放的话,可以节省空间。
再来讲讲#Pragma pack()
#pragme pack是设置默认对齐值的,vscode里的默认对齐值是8,相当于#pragme pack(8)
这也可以得出一个结论,如果括号里的值大于8,那这句话就没啥用了。