目录
数据对齐概念
Alignment:要求数据的地址是相应的边界地址
- 目前机器字长为32位或64位,主存按一个传送单位(32/64/128位)进行存取,而按字节编址,例如:若传送单位为64位,则每次最多读写64位,即:第0~7字节同时读写,第8~15字节同时读写,……,以此类推。按边界对齐,可使读写数据位于8i~8i+7(i=0,1,2,…) 单元
- 指令系统支持对字节、半字、字及双字的运算
- 各种不同长度的数据存放时,有两种处理方式:
– 按边界对齐(若一个字为32位)
• 字地址:4的倍数(低两位为0)
• 半字地址:2的倍数(低位为0)
• 字节地址:任意
– 不按边界对齐
坏处:可能会增加访存次数!
对齐
假设1个字=32位,主存每次最多存取一个字,按字节编址,则每次只能读写某个字地址开始的4个单元中连续的1、2、3或4个字节 。
边界对齐
例如:int i, short k, double x, char c,变量按如下顺序在内存中存储,则:&i=0; &k=4; &x=8; &c=16;。
取x:需要2个周期
取j:需要1个周期
边界不对齐
&i=0; &k=4; &x=6; &c=14;
取x:3个周期
取j:2个周期
最简单的对齐策略
按其数据长度进行对齐。
- – Windows采用策略:int型地址是4的倍数,short型地址是2的倍数,double和long long型的是8的倍数,float型的是4的倍数,char不对齐
- Linux采用更宽松策略:short型是2的倍数,其他类型如int、float、double和指针等都是4的倍数
对齐举例
struct S1 { int i; char c; int j; }; struct S2 { int i; int j; char c; };
在要求对齐的情况下,哪种结构声明更好?
S2比S1好
对齐方式的设定
#pragma pack(n)
• 为编译器指定结构体或类内部的成员变量的对齐方式。
• 当自然边界(如int型按4字节、short型按2字节、float按4字节)比n大时,按n字节对齐。
• 缺省或#pragma pack() ,按自然边界对齐。比n小则按自然边界对齐。
__attribute__((aligned(m)))
• 为编译器指定一个结构体或类或联合体或一个单独的变量(对象)的对齐方式。
• 按m字节对齐(m必须是2的幂次方),且其占用空间大小也是m的整数倍,以保证在申请连续存储空间时各元素也按m字节对齐。
__attribute__((packed))
• 不按边界对齐,称为紧凑方式。