什么是内存对齐
现代计算机中内存空间都是按照 byte 划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但是实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地址的值是某个数k(通常它为4或8)的倍数,这就是所谓的内存对齐。
为什么要进行内存对齐
尽管内存是以字节为单位,但是大部分处理器并不是按字节块来存取内存的.它一般会以双字节,四字节,8字节,16字节甚至32字节为单位来存取内存,我们将上述这些存取单位称为内存存取粒度。
现在考虑4字节存取粒度的处理器取int类型变量(32位系统),该处理器只能从地址为4的倍数的内存开始读取数据。
假如没有内存对齐机制,数据可以任意存放,现在一个int变量存放在从地址1开始的联系四个字节地址中,该处理器去取数据时,要先从0地址开始读取第一个4字节块,剔除不想要的字节(0地址),然后从地址4开始读取下一个4字节块,同样剔除不要的数据(5,6,7地址),最后留下的两块数据合并放入寄存器。这需要做很多工作。
因此为了提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;然而,对齐的内存访问仅需要一次访问。
如何进行内存对齐
1.通过编译器来指定对齐长度
每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。例如gcc中默认#pragma pack(4),可以通过预编译命令 #pragma pack(n),n = 1,2,4,8,16 来改变这一系数。
#pragma pack(n) //注意n只能为1,2,4,8,16
通过编译器修改也存在自己的局限性,例如:
1.我们如果想要使用AVX指令集,就需要对数据进行32位的对齐,因此需要寻找其它的方法。
2.如果使用不同的CPU进行编程(部分CPU是不支持非对齐访问的),可能会遇到内存不对齐导致程序无法运行的情况。
2.利用内存分配函数
贴一段关于该内存函数的官方定义:
/* Allocate SIZE bytes allocated to ALIGNMENT bytes. */
extern void *memalign (size_t __alignment, size_t __size)
__THROW __attribute_malloc__ __wur;
应用实例:
int *i;
i = (int *)memalign(32 , 4 * 100);//分配内存大小为400个字节的空间,数据以32位的方式对齐。