文章原文在我的个人博客
为什么会有内存对齐?
为了访问未对齐的内存,处理器需要作两次内存访问;而,对齐访问仅需要一次访问。
对齐参数
32位系统中,默认4字节对齐(32位系统CPU字长是4字节)
- 在Windows(32)/VC6.0下各种数据类型的变量的自身对齐参数就是该数据类型变量所占字节数的大小
- 在Linux(32)/GCC下double类型下的对齐参数为4
- Linux(32)/GCC下如果该数据类型的长度没有超过CPU的字长,则以该数据类型变量的长度作为自身对齐参数
- 如果超过了CPU字长,则自身对齐参数为CPU字长
字节对齐原则
- 结构体每个成员相对结构体首地址的偏移量(offset)是对齐参数(此对齐参数是取每个变量自身对齐参数和系统对齐参数两者中较小的一个)的整数倍,如果有需要会在每个成员之间填充字节
- 编译器在为结构体成员开辟空间时,首先检查预开辟空间的地址相对于结构体首地址的偏移量是否为对齐参数的整数倍,若是,则存放该成员,否则,反之
- 结构体变量所占空间的大小是对齐参数大小的整数倍,如有需要会在最后一个成员末尾填充若干字节使得所占空间是对齐参数 (对结构体中所有变量的对齐参数的最大值和系统默认对齐参数#pragma pack(n)比较,较小者作为对齐参数)的整数倍
static修饰的变量所占空间没有被算入,因为其存储在.bss段/.data段
内存对齐的关键字
GCC推荐的对齐指令
__attribute__((packed)) // 一字节对齐使用时,直接接放在进行内存对齐的类型定义后面,其作用范围为使用该类型定义的变量
__attribute__((aligned(n))) // 用法同上,使整个结构体进行n字节的对齐(n为2的幂次方)
GCC支持但不推荐的对齐指令
#pragma pack(n) // 放在自定义字节对齐的数据结构开头,指定编译器对齐参数为n字节
定义结构体
#pragma pack() // 放在自定义字节对齐的数据结构结尾,取消指定对齐参数,恢复缺省参数
网友评论