我的恶魔未婚夫理论上计算机对于任何变量的访问都可以从任意位置开始,然而实际上系统会对这些变量的存放地址有限制,通常将变量首地址设为某个数N的倍数,这就是内存对齐。
1. 硬件平台限制,内存以字节为单位,不同硬件平台不一定支持任何内存地址的存取,一般可能以双字节、4字节等为单位存取内存,为了保证处理器正确存取数据,需要进行内存对齐。
提高CPU内存访问速度,一般处理器的内存存取粒度都是N的整数倍,假如访问N大小的数据,没有进行内存对齐,有可能就需要两次访问才可以读取出数据,而进行内存对齐可以一次性把数据全部读取出来,提高效率。
1. 数据成员对齐规则:struct或者union的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员都按照#pragma pack数值和这个数据成员自身大小中更小的那个进行对齐。
2. 整体对齐规则:struct或者union的首地址按照内部最大数据成员的大小和#pragma pack数值较小的那个N进行对齐,并且结构体的总大小为N的整数倍,如有必要编译器也会在最后一个成员后面填充一些字节用于对齐。
// 创建给定类型对象大小满足对齐要求的未初始化内存块,在一个内存对齐的缓冲区上创建对象
使用方式上面已经介绍过了,Align大小也可以不填,默认会是采用最大最有益的对齐大小,大家可能源码里有些语句不了解含义,如下:__attribute((packed))告诉编译器取消编译中的内存对齐优化,采用实际占用的字节数进行对齐。
__attribute((aligned(N))) 告诉编译器在编译过程中按照N字节对齐,经过测试这个N只有大于结构体中最大的变量的大小才有用。
__attribute__((aligned)) 后面不接数字,告诉编译器根据目标机制采用最大最有益的方式对齐,基本上就是16字节对齐。
// g++空结构体的内存大小为1,需要分配1字节用于占位,C++编译器不允许对象为0长度,无法获取地址等
// __attribute__((packed))告诉编译器取消编译中的内存对齐优化,采用实际占用的字节数进行对齐
// __attribute__((aligned(N))) 告诉编译器在编译过程中按照N字节对齐,经过测试这个N只有大于结构体中最大的变量的大小才有用
// __attribute__((aligned)) 后面不接数字,告诉编译器根据目标机制采用最大最有益的方式对齐,基本上就是16字节对齐
通过结果可知,一个类带有虚函数,类的大小会多8个字节,这8个字节是虚函数表指针的大小,指针类型为长整型long,在32位机器上是4字节,64位机器上是8字节。
|