现代计算机中内存空间都是按照 byte 划分的,也就是字节,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐
从cpu的角度来说,CPU不会一次读取或写入一个字节的内存。相反,CPU一次以2、4、8、16或32字节块访问内存。这样做的原因是提升性能:
访问4字节或16字节边界上的地址比访问1字节边界上的地址快得多。
下图说明了CPU如何以4字节内存访问粒度访问4字节数据
那么如果数据/内存没有对齐的话,则CPU必须执行额外的工作才能访问数据,如下图,CPU一次性访问4个字节:
没有对齐的话就会经历:
装入2个数据块,移出不需要的字节,然后将它们组合在一起。此过程肯定会降低性能,浪费CPU周期,只是为了从内存中获取正确的数据。
那么现在的话,对齐这部分编译器会帮我搞定,一般不需要自己动手,但也排除一些极端情况。在32位或者64位x86系统中,对齐方式与其数据类型的大小基本相同。编译器在其自然长度边界上对齐变量。 CPU就可以正确处理未对齐的数据。
举一个简单的例子:
我们知道,int类型占4个字节的空间,char一般就是1个,如果把它们放在一个结构体中,理论上占 4+1=5个byte,但由于cpu的访问和对齐的原因,实际上,默认情况下它会占8个byte,可以sizeof以下就知道了
struct User{
int mid;
char gender;
};
原理如图:
每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。可以通过预编译命令#pragma pack(n),n=1,2,4,8,16 来改变这一系数,其中 n 就是你要指定的“对齐系数”。
如果上面那个例子,对齐系数改成1,那么就只占用5个byte,但这样会使得cpu负担更大
在某些情况下,通过为数据结构指定自定义对齐方式,可以显着提高性能或节省内存.
原文:https://www.cnblogs.com/zhouyc/p/13676254.html