内存对齐

来源:互联网 发布:linux服务器清屏命令 编辑:程序博客网 时间:2024/06/07 03:06

     什么是对齐,以及为什么要对齐: 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访

问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问,这就需要各类型数据按照一定的规

则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。 对齐的作用和原因:各个硬件平台对存储空间的处理上有

很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。其他平台可能没有这种情况,但是最常见的是如

果不按照适合其平台要求对数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个

int型(假设为32位系统)如果存放在偶地址开始的地方,那么一个读周期就可以读出,而如果存放在奇地址开始的地方,就

可能会需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该int数据。显然在读取效率上下降很多。这也是空

间和时间的博弈。 对齐的实现 通常,我们写程序的时候,不需要考虑对齐问题。编译器会替我们选择时候目标平台的对齐策

略。当然,我们也可以通知给编译器传递预编译指令而改变对指定数据的对齐方法。 但是,正因为我们一般不需要关心这个

问题,所以因为编辑器对数据存放做了对齐,而我们不了解的话,常常会对一些问题感到迷惑。最常见的就是struct数据结构

的sizeof结果,出乎意料。为此,我们需要对对齐算法所了解。

          一般编译器都设定了默认的变量字节对齐方式,如vc 6.0,vs2010都设定8为默认的变量字节对齐方式(#pragma

pack(8))。我们也可以设定自己的字节对齐方式(如 #pragma pack(4)) 。

 

          对齐规则:

          1. 结构体(或联合体,类等)第一个变量的偏移量为0,之后的每个变量(a)的偏移量是这个变量(a)自身所占

字节数(sizeof(a))与变量字节对齐方式(n)中较小值的的整数倍,即min(sizeof(a) , n)的整数倍。

          2. 结构体(或联合体,类等)内所有变量都计算完后,找出结构体内所占字节数最多的变量(a) ,取sizeof(a)

与变量字节对齐方式(n)中的较小值x,sizeof( 结构体)的大小等于x的整数倍。

 

         看两个例子:

             struct s1
            {
                  int a;
                  char q;
                 double s;
            };
             struct s2
            {
                  char f;
                  double s;
                  int a;
            };

          在vs2010下运行sizeof(s1) == 16 , sizeof(s2) == 24。a的偏移量为0,站4个字节,q站一个字节小于8,所以q

的偏移量是1的整数倍,最小能取4,那么s的偏移量只能从5算起了,同理s的偏移量是8的整数倍最小取8,所以s1里变量要分

配16个字节。再有s1里最大变量s站8 字节(==变量字节对齐方式(8)),所以sizeof(s1)应该为8的整数倍,正好取16。s2同

理。

         如果在开头加一句#pragma pack (4),那么结果又不一样了。

         在c++中sizeof(类)的大小不仅与变量的声明顺序,变量的字节对齐方式有关,还跟类中是否存在虚函数以及类的

继承方式等有关。

        

原创粉丝点击