内存对齐

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字节对齐的。

posted @ 2023-09-23 20:09  mjy66  阅读(81)  评论(0编辑  收藏  举报