首先来看个栗子
#include<stdio.h>
struct CYStruct{
int a; //4
double b; //8
char c ; //1
short d; //2
}Mystruct;
int main ()
{
printf ("===%d==",sizeof(Mystruct);
return 0;
}
打印结果:===24==
我们知道在64位系统中,int是4字节 double是8字节 char是1字节,short是2字节,加一起不是15字节么?打印的结果却是24字节。
这就是因为内存对齐,不仅仅是因为8字节对齐,下面会讲内存对齐的原则。
注:本文讨论的内容均是在64位系统下。
What?
一、首先我们来认识下什么是内存对齐。
计算机中内存空间是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是:在访问特定类型变量的时候通常在特定的内存地址访问,这就需要对这些数据在内存中存放的位置有限制,各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。
内存对齐是编译器的管辖范围。表现为:编译器为程序中的每个“数据单元”安排在适当的位置上。
why?
二、为什么需要内存对齐
参考百度百科
1、平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2、性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
现在假如没有进行内存对齐。
如上图栗子,如果需要获取b,需要在内存中多次偏移读取,才能找到B。如果有内存对齐,现在只要偏移间隔为B所占内存的倍数查找即可。大大减少了查找成员所需要的时间。
How?
三、内存对齐原则
1:数据成员对⻬规则:结构(struct)(或联合(union))的数据成员,第
一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要
从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,
结构体等)的整数倍开始(比如int为4字节,则要从4的整数倍地址开始存
储。 min(当前开始的位置mn)m=9n=4
9 10 11 12
2:结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从
其内部最大元素大小的整数倍地址开始存储.(struct a里存有struct b,b
里有char,int ,double等元素,那b应该从8的整数倍开始存储.)
3:收尾工作:结构体的总大小,也就是sizeof的结果,.必须是其内部最大成员的整数倍.不足的要补⻬。
现在我们来对着上面的原则算一下上面的栗子
struct CYStruct{
int a; //4 [0-3]
double b; //8 [8-15]
char c ; //1 [16]
short d; //2 [18-19]
}Mystruct; //最大成员内存为8字节,必须是8的倍数,所以补齐是24字节。
这里附上字节占用表,当然32位和64位还是有区别的。总结
内存对齐就是制定一定的规则,用空间换时间,让系统更快的获取所需要的内存。