内存对齐研究

    最近复习时,看到内存对齐,于是对这一块研究了下,记录下来。

(1)内存对齐概念

一个变量在内存中的地址是其长度的整数倍,称之为自然对齐。比如对一个int型变量,其地址是0x00000004,表示该变量是自然对齐的。

(2)为什么需要内存对齐

主要是提高cpu访问内存的速度。如果不对数据进行对齐,cpu读取数据可能需要两次或者更多次,然后在合并成需要的数据类型,这样效率太低了。

例如:对一个int类型变量

      (a)地址为0x00000004,此时是自然对齐,cpu只需要一次就完成了读取。

      (b)地址为0x00000002,此时数据没有对齐,cpu先读取一个short,然后在读取一个short,然后组合成一个int类型数据,用了两次。

      (c)地址为0x00000003,此时数据没有对齐,cpu先读取一个char,然后读取一个short,然后在读取一个char,然后组合成int类型,用了三次。

可见数据对齐对提高cpu访问数据的效率很有必要。

(3)内存对齐规则

有四个基本概念:

(a)数据类型自身对齐值

   char类型自身对齐值1个字节,short类型为2,int,float为4,double为8。

(b)结构体或者类自身对齐值

   成员自身对齐值的最大值

(3)指定对齐值

   #define pack (n),表示按n个字节对齐。

(4)数据成员、结构体和类的有效对齐值

          自身对齐值和指定对齐值中的较小值。

有效对齐值N决定了最终数据存放地址的值,最终要的。有效对齐到N,表示数据地址对N求余为0,即"数据地址%N = 0"。

对齐的三条规则:

(a)成员对齐:结构体个成员的其实地址必须是成员数据类型长度的整数倍。

(b)结构体整体需求:结构体总的长度必须是成员最大数据类型长度的整数倍。

(c)编译器对齐指令:vc中#pragma pack(n),按照n字节进行对齐。

例子如下:

1、没有用编译器对齐指令#pragma pack(n)

   struct a
   {  
      char ax;
      int  bx;
      short cx;  
   };
ax的其实地址为0x00000000,自身对齐值为1,0x00000000%1=0,第一个字节存ax。而int类型自身对齐值为4,0x00000001%4!=0,0x00000002%4!=0,0x00000003%4!=0,0x00000004%4=0,所以bx存储的其实地址为0x00000004,还有后续的连续三个字节,0x00000005,0x00000006,0x00000007。cx的自身对齐值为2,其实地址0x00000008%2=0,后续占用一个字节0x00000009;按照这样算来,struct a应该占用10个字节,亲,别忘了还要考虑整体需求。结构中成员最大数据类型为int,总的字节数应该是int长度的整数倍,所以short后还需要补两个字节,共12个字节。即sizeof(a)=12。

2、使用编译器对齐指令#pragma pack(n)
分两种情况讨论:

(a)n比结构体中最大数据类型大,此时采用默认对齐方式

#pragma  pack (8)

   struct a
   {  
      char ax;
      int  bx;
      short cx;  
   };
此时,struct a的长度12,sizeof(a)=12。

(b)n比结构体中最大数据类型大,此时按照n进行对齐

#pragma  pack (2)

   struct a
   {  
      char ax;
      int  bx;
      short cx;  
   };
       ax占用0x00000000,0x00000001两个字节,bx占用0x000000002,x000000003,x000000004,x00000005四个字节,cx占用0x000000006,x00000007两个字节。故struct a共占用8个字节,sizeof(a)=8。


        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值