读书人

为什么要内存对齐?解决思路

发布时间: 2013-11-21 23:38:25 作者: rapoo

为什么要内存对齐?
能具体点说么。可以用11**1111这样的形式图解。*代表空出来的内存。 一
[解决办法]
普通程序员心目中的内存印象,由一个个的字节组成,而CPU并不是这么看待的。CPU把内存当成是一块一块的,块的大小可以是2,4,8,16字节大小,因此CPU在读取内存时是一块一块进行读取的。块大小成为memory access granularity(粒度) 本人把它翻译为“内存读取粒度” 。默认的读取粒度是4字节大小。
这个粒度可以通过#pragma pack()来调整
那么编译器是按照什么样的原则进行对齐的?
1:数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储。

2:结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储.(struct a里存有struct b,b里有char,int ,double等元素,那b应该从8的整数倍开始存储.)

3:收尾工作:结构体的总大小,也就是sizeof的结果,.必须是其内部最大成员的整数倍.不足的要补齐.
[解决办法]
无量天尊,看在你一片求知若渴之心,贫道就把这篇珍藏多年的文章送与你,细读之,必大悟!!!
http://www.cppblog.com/snailcong/archive/2009/03/16/76705.html
[解决办法]
目前新的更X的CPU对这个有什么别的用处不是很清楚,但早期的CPU之所以要求(或prefer)内存对齐是因为地址总线的条数之类的问题吧。 比如16位地址总线只能访问65536个字节的内存,但如果地址单位是4字节的话,就可以访问4位的内存大小。

拿x86来说,
x86是32位寄存器,所以一次一般读取4个字节,并且读取只能从4字节边界开始。如果你访问单个字节内存,CPU会把其它3个字节扔掉。 如果你要读取两个字节,但位于4字节边界两侧,CPU需要先读前边4字节,然后扔掉三个字节,再读取后边4字节,然后再扔掉其中的三个字节,然后把两次读取的结果拼成一个双字节。 所以双字节最好对齐到双字节边界,以保证CPU一次就可以读取。 而4字节值对齐到4字节边界也是一个道理。

这也是x86牛X,直接支持非对齐读取(虽然慢点),有些CPU是不支持这种跨边界读取的,所以C语言编译器有时要生成额外代码以处理跨界读取,其效率更慢。
[解决办法]
效率只是一个方面,有些甚至影响正确性。

在某些处理器上,只能采用自然对齐的访问,否则产生硬件异常,如原来Nokia的一些芯片。

读书人网 >C语言

热点推荐