资源描述:
《32vc内存对齐准则》由会员上传分享,免费在线阅读,更多相关内容在工程资料-天天文库。
1、VC内存对齐准则(Memoryalignment)本文所有内容在建立在一个前提下:使用VC编译器。着重点在于:VC的内存对齐准则;同样的数据,不同的排列有不同的大小,另外在有虚函数或虚拟继承情况下又有如何影响?内存对齐?!What?Why?对于一台32位的机器来说如何才能发挥它的最佳存取效率呢?当然是每次都读4字节(32bit),这样才可以让它的bus处于最高效率。实际上它也是这么做的,即使你只需要一个字节,它也是读一个机器字长(这儿是32bit)。更重要的是,有的机器在存取或存储数据的吋候它要求数据必须是对齐的,何谓对齐?它要求数据的地址从4的
2、倍数开始,如若不然,它就报错。还有的机器它虽然不报错,但对于一个类似int变量,假如它横跨一个边界的两端,那么它将要进行两次读取才能获得这个int值。比方它存储在地址为2〜5的四个字节中,那么要读取这个int,将要进行两次读取,第一次读取0〜3四个字节,第二次读取4〜7四个字节。但是如果我们把这个整形的起始地址调整到0,4,8…呢?一次存取就够了!这种调整就是内存对齐了。我们也可以依次类推到16位或64位的机器上。边界该如何调整对于32位的机器来说,它当然最渴望它的数据的大小都是4Byte或者4的倍数Byte,这样它就能最有效率的存取数据,当然如
3、果数据小T4Byte,那也是没问题的。那么编译器要做的便是尽量满足这个要求。这两天我断续对VC做了一些实验,并总结如下三条准则,你要明白的是这并非來自微软的官方文档,但我自以为这些准则或许不全但应该都是正确的:•变量存放的起始位置2应为变量的大小与规定对齐量1中较小者的倍数。例如,假设规定对齐量为4,那么char(1byte)变量应该存储在偏移量为1的倍数的地方,而整形变量(4byte)则是从偏移量为4的倍数的地方,而double(8byte)也同样应存储在偏移量为4的倍数的地方,为什么不是8?因为规定对齐量默认值为4,而4v8。在VC中默认对齐
4、量为8,而非4。•结构体整体的大小也应该对齐,对齐依照规定对齐量与最大数据成员两者中较小的进行。•Vptr影响对齐而VbcPoint(Virtualbaseclasspointer)不影响。一个实例对于类T:classT{charc;inti;doubled;};将其sizeof输出后的大小为16,其内存布局如图「变量c从偏移量为0开始存储,而整形i第一个符号条件的偏移量为4,double型d的第一个符号条件的为8。整个对象的大小为16,不需要再进行额外的对齐。图T(类T的内存布局):charc因对齐而填同样的数据,不同的大小再看类L,它与T存储
5、同样类型的数据,仅仅是顺序不同罢了,那么它sizeof输出的大小是多少呢?类L:classL{charc;doubled;inti;};它sizeof后的结果或许会令你大吃一惊,或许不会(如果你有认真读前面的两条准则)。Lsizeof后的结果是24!同样是一个int,一个char,一个double却整整多出了8个字节。这期间发生了什么?我们依据前面两条规则来看看。C存储于0的位置,1-7都不能整除8,所以d存储在8-15,16给i正好合适,i存储在16〜19。总共花费了20个字节,抱歉不是8的倍数,还得补齐4个。现在你可以看看图L的关于类L的内存
6、布局,再比较一下类L和类T的内存布局。图L(类L的布局)charcdoubledinti我得出了这样一条并不权威的结论,因为我还没听有人这样说过:在声明数据成员的时候,将最大字节数的变量放在最前面3,切忌不要将大小差距很大的类型交替声明。Vptr影卩向对齐而VbcPoint(Virtualbaseclasspointer)不影响前面的实例只涉及前两条准则,现在我们來看看第三条的两个实例:classX{chara;};classY:virtualpublicX{};Y的大小为:a占一个字节,VbcPoint(我称他为虚基类指针)占四个字节。我们不论
7、a与VbcPoint的位置如何摆放,如果将VbcPoint等同于一个成员数据来看的话,sizeof(Y)都应该为8.实际上它是5!就我目前的水平,我只能先将其解释为VbcPoint不参与对齐。对于vptr这个问题则不存在:classX{chara;virtualintvfc(){};}sizeof(X)的大小确实为8.关于#pragmapack(n)用#pragmapack(n)改变规定对齐量试试9。1.规定对齐量:实际上并没有这么一个名词,是我为了方便而造出来的。在VC屮这个“规定对齐量”会有一个默认值,这个默认值一般为8,我原来一直以为这个值
8、以为是4,至于它为什么为8,我现在还不知道。。我们也可以通过#pargmapack(n)来规定这个值,目前n可以为1,2,4,8,16。