内存对齐是什么神奇的技术,为何如此重要?

摘要:1、内存对齐是什么? ​	计算机的内存就好像一个很大的数组,访问内存的时候,看似是可以从任何地址开始,但是实际上为了简化形成处理器和内存系统之间的接口设计,不同类型的数据会按照一定的规则在空间上排列,并不是按照顺序一个接着一
1、内存对齐是什么? ​ 计算机的内存就好像一个很大的数组,访问内存的时候,看似是可以从任何地址开始,但是实际上为了简化形成处理器和内存系统之间的接口设计,不同类型的数据会按照一定的规则在空间上排列,并不是按照顺序一个接着一个排放,这种排放方式就是内存对齐。 2、需要内存对齐的原因 ​ 内存对齐能够提升处理器读取数据的效率,比如,假设一个处理器总是从内存中读取8个字节或者8个字节的倍数,如果储存double类型数据的地址不是8的倍数,那么可能需要读取两块8个字节的内存才能读取到这个double类型数据,若double类型数据的地址是8的倍数,则读取一次内存就能读取到这个double类型数据。 3、如何实现内存对齐 ​ 在写程序的时候,优秀的编译器将会自动实现对齐的策略,一般的编译器比如VS、DEV C++等,默认都是8位字节对齐,就算不实现自动对齐,编译器也不会报错,只是会在效率上受影响,内存对齐可以看成一种使用空间效率换时间效率的方法。 ​ 对齐的原则:任何K字节的基本对象的地址都必须是K的倍数,其基本类型的对齐K参数如下表所示: K 类型 1 char 2 short 4 int,float 8 long,double,char* ​ 每种类型都按照上表的K来完成内存对齐。编译器在汇编代码中放入命令,来指令全局数据所需的对齐,例如,若要保证数据的起始地址是8的倍数,则可以包含以下命令: .align 8 ​ 在C语言中设置对齐的方式是,在开头声明如下代码: #pragma pack(value) //value为要设置的字节对齐数 ​ 对于包含结构的代码,编译器会在字段的分配中插入间隙,从而保证每个结构元素都满足它的对齐要求,例如下面这个结构,假设编译器设置为4字节对齐: struct a { int i; //4个字节 char c; //1个字节 int j; //4个字节 }; int main() { cout<<sizeof(a); } ​ 理论上来说,这个结构体由两个int和一个char组成,其内存大小为9字节,然而输出为: ​ 理论上的内存分布,如图所示: ​ j的地址偏移为5,无法满足4字节的对齐要求,因此编译器会在字段c和j之间插入一个3字节的间隙: ​ 插入间隙之后,j的偏移量为8,便满足4字节的对齐要求,因此整个结构的大小也变为12字节。除了考虑结构体内的元素地址外,结构体的起始位置也就是图中的"0",不一定是真实内存中的0,可能是任意一段内存的起点,所以其结构体的起点,也就是struct a*类型的指针必须也满足4字节对齐,这样也就保证了结构体内的元素在整体内存布局下也是满足4字节对齐的。