内存对齐

1、内存对齐的缘由

  大部分的参考资料都是如是说的:
ios

  一、平台缘由(移植缘由):不是全部的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,不然抛出硬件异常。
  二、性能缘由:数据结构(尤为是栈)应该尽量地在天然边界上对齐。缘由在于,为了访问未对齐的内存,处理器须要做两次内存访问;而对齐的内存访问仅须要一次访问。数据结构


 


 

2、内存对齐的规定:

 
  1.数据成员对齐规则:结构(struct或联合union)的数据成员,第一个数据成员放在offset为0的地方,之后每一个数据成员存储的起始位置要从该成员自身大小的整数倍开始(好比int在32位机为4字节,则要从4的整数倍地址开始存储)。编译器在给结构体开辟空间时,首先找到结构体中最宽的基本数据类型,而后寻找内存地址能被该基本数据类型所整除的位置,做为结构体的首地址。将这个最宽的基本数据类型的大小做为上面介绍的对齐数。
 
   2.结构体做为成员:若是一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。为结构体的一个成员开辟空间以前,编译器首先检查预开辟空间的首地址相对于结构体首地址的偏移是不是本成员的整数倍,如果,则存放本成员,反之,则在本成员和上一个成员之间填充必定的字节,以达到整数倍的要求,也就是将预开辟空间的首地址后移几个字节。
 
  3.结构体成员相对首地址偏移量必须是成员大小的整数倍,也就是内存对齐。
 
  4.结构体总大小必须是对齐模数的整数倍。
 


 


 

3、计算

#include <stdlib.h> #include <iostream> using namespace std; int main() { struct AA { char a; char b; char c; }; cout << sizeof(AA) << endl; system("pause"); } 

  这个比较简单,能够根据上面的表格能够直接计算出来。性能

 


 

  来个有点难度的spa

#include <stdlib.h> #include <iostream> using namespace std; int main() { struct AA { char a; int b; char c; }; cout << sizeof(AA) << endl; system("pause"); }

  猜猜结果会是多少? 会是 5 吗??3d

  来详细了解一下:code

 

  实际上会如图所示吗???blog

  当以如图的方式存放数据时,系统访问char a 时,只需读取一个字节,但当访问 int b 的时候,先要读取一个字节,在读取四个字节,才能读到int b的值。这样系统在访问数据时要先判断各个数据的字节大小,在进行读取,这样就会浪费时间。为了节省时间,会以下的方式去存储数据:内存

  在存储数据时,会对char a 补充 3 个字节,这样在访问 char a、int b 时,每次只需读取 4 个字节就能够,以一种空间换时间方式来提升效率。编译器

  当如图存放数据以后,整个结构体的大小为 9 个字节。这与计算输出的结果不符(还记得,经过程序计算的大小为 12 个字节),这是为何吗??io

  还记得前面说的内存对齐的第四条规则吗??

4.结构体总大小必须是对齐模数的整数倍。

  在上面给出了一个表格,上面有常见数据类型的模数,那咱们如何肯定一个结构提的模数呢???

  其实结构体的模数等于其内部模数最大的成员类型的模数

 struct AA { char a; int b; char c; };

  对于结构体AA来讲,他的模数就是 4。

  则该结构体的大小必须是 4 的整数倍,因此在最后还会补充 3 个字节(以下图)。

  这样结构体AA的大小就是 12 个字节。


  在添加点难度:
#include <stdlib.h> #include <iostream> using namespace std; int main() { struct AA { char a; int b; char c; }; struct BB { char d; int e; double f; AA g; }; cout << sizeof(BB) << endl; system("pause"); }

  先来看看答案:

  来分析一下:

 

 

  到结构AA,来看看结构体AA的状况:

  因此接下来应该以下图:

  由图可知 结构体BB一共占据32个字节的内存,到这里就完了吗??

  还记得 内存对齐的第四条规则吗??

4.结构体总大小必须是对齐模数的整数倍。

  结构体BB的模数为多少呢??

  由于double e 的模数最大为 8 ,因此BB的模数也为8。32 是 8 的倍数,因此结构体BB只占 32 个字节。



4、自定义模数大小

  能够经过#pragma pack() 自定义模数的大小。

#include <stdlib.h> #include <iostream> using namespace std; #pragma pack(1) int main() { struct AA { char a; int b; char c; }; struct BB { char d; int e; double f; AA g; }; cout << sizeof(BB) << endl; system("pause"); }

  将模数的大小自定义为 1 后,运行结果以下:

  当模数大小定义为 2 时,运行结果以下:

  能够本身去试试画图理解。

相关文章
相关标签/搜索