内存对齐之结构体大小的计算

结构体变量的地址受到内存对齐规则的影响,使得结构体成员并不是在内存中“紧挨”着的

可以参照如下结构体:

   1 #include <stdio.h>
   2 struct s{
   3     char a;
   4     double b;
   5     int c; 
   6     short d;
   7     double e;
   8 };  
   9 int main()
  10 {
  11     struct s s1;
  12     printf("%x
",(int*)&(s1.a));
  13     printf("%x
",(int*)&(s1.b));
  14     printf("%x
",(int*)&(s1.c));
  15     printf("%x
",(int*)&(s1.d));
  16     printf("%x
",(int*)&(s1.e));
  17     printf("%d
",sizeof(s1));
  18     return 0;
  19 } 

运行结果如下:

最终,我用EXCEL表格的形式,做出如下的结构体成员的内存分配位置,如下图黄色为实际存在数据的内存单元白色空格为适应内存对齐而进行的偏移量需要注意系统默认是4字节对齐的,所以一行的最大宽度也就是四个字节。

所以结构体内存分配的规则个人总结如下:

1.首成员起始地址设为0。

2.每个成员x的起始地址必须是min(4,sizeof(x))的倍数。

关于总结的第2点可以在《深入理解Linux内核》内存管理章节中的“对齐内存中的对象”小节中找到依据:

slab分配器所管理的对象可以在内存中进行对齐,也就是说,存放它们的内存单元的起始物理地址是一个给定常量的倍数,通常是2的倍数。这个常量就叫对齐因子(alignment factor)。

由于系统默认4字节对齐,所以我认为文章所提到的对齐因子最大值也就是4了。即min(4,sizeof(x))。

这个规则我使用了多种情况验证,都是正确的。如有错误,还请各位大侠批评指正哈!

在VC上可以通过如下宏来改变内存对齐的字节范围,即改为8字节内存对齐

#pragma pack (8)

同样可以用《深入理解Linux内核》内存管理章节中的“对齐内存中的对象”小节中来解释内存对齐的意义:

通常情况下,如果内存单元的物理地址是字大小(即计算机的内部内存总线的宽度)对齐的,那么,微机对内存单元的存取会非常快

原文地址:https://www.cnblogs.com/kunshanpipixia/p/14166207.html