关于内存对齐详细解释
http://www.pianshen.com/article/5293272183/
什么是内存对齐?
在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自的空间相加,这里涉及到内存对齐的问题。访问未对齐的内存,处理器需要访问两次(数据先读高位再读低位然后进行拼接),而访问对齐的内存,只需要一次。为了提高效率,所以进行内存对齐。windows的默认对齐数是8,linux中默认对齐数为4.
为什么会产生内存对齐的原因?
1.平台原因:
某些平台只能在特定的地址处访问特定类型的数据。不是所有的硬件平台都能访问任意地址上的任意数据,某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常
2.性能原因:
(1)数据结构(尤其是栈)应该尽可能在自然边界上对齐。
(2)为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存仅需要访问一次。(CPU在读取内存的时候是一块一块进行读取的,块的大小称为(memory granularity)内存读取粒度)
编译器是怎样进行内存对齐的优化的?
在内存中,编译器按照成员列表顺序分别为每个结构体变量成员分配内存,在存储过程中需要满足边界对齐要求时,编译器会在成员之间留下额外的内存空间。
结构体或联合体的数据成员、第一个成员放到0编译地方,以后每个数据成员放到自身对齐的整数倍偏移处。(结构体大小必须是最大对齐数的整数倍)。
字节对齐可以程序控制,采用指令:
#pragma pack(1)//1字节对齐
#pragma pack(2)//2字节对齐
#pragma pack(4)//4字节对齐
#pragma pack(8)//8字节对齐
举个栗子:
struct A{
char c;
double d;
short s;
int i;
}
当系统以8字节对齐时
程序验证一下:
-
-
-
-
-
struct A
-
{
-
char c;
-
double d;
-
short s;
-
int i;
-
};
-
int main()
-
{
-
struct A a;
-
printf("A所占大小为%d字节\n",sizeof(struct A));
-
-
return 0;
-
}


我们再来看看为什么内存不对齐会影响读取速度?
假设CPU要读取一个4字节大小的数据到寄存器中(假设内存读取粒度是4),分两种情况讨论:
1.数据从0字节开始
2.数据从1字节开始
解析:当数据从0字节开始的时候,直接将0-3四个字节完全读取到寄存器,结算完成了。=
当数据从1字节开始的时候,问题很复杂,首先先将前4个字节读到寄存器,并再次读取4-7字节的数据进寄存器,接着把0字节,4,6,7字节的数据剔除,最后合并1,2,3,4字节的数据进寄存器,对一个内存未对齐的寄存器进行了这么多额外操作,大大降低了CPU的性能。但是这还属于乐观情况,上文提到内存对齐的作用之一是平台的移植原因,因为只有部分CPU肯干,其他部分CPU遇到未对齐边界就直接罢工了。

浙公网安备 33010602011771号