一、问题提出
怎样的数据访问是对齐的?很简单
aligned: C内存地址%数据大小 ==0;自然对齐
unaligned:不满足上述规则,这个数据是非对齐的
简单的说,就是char类型无对齐要求;short类型的数据地址最后一位是0;int型数据地址最后两位为0;
非对齐访问对X86//Sparc这类芯片会导致访问开销问题,对于ARM/MIP/ACPHA/IA-64这类CPU会导致异常。
本文的所有讨论基于32位的RISC/CISC CPU和GCC编译器
二、对齐处理
内存对齐的几个处理场景:
1.CPU自动对齐
2.编译器模拟对齐访问
3.OS处理对齐
4.结构体的对齐问题
5.malloc的对齐问题
malloc明显存在内存对齐问题,因为其返回的类型地址总会转换需要的指针类型;所以,malloc函数返回的地址总是适当对齐的,使它可以在各种情况下使用,VC采用8字节对齐。
6.编译器的对齐选项
GCC编译器对数据的对齐,提供很好支持。
6.1.使用#pragam pack
#pragam pack(n) 设置对齐
数据定义
#pragam pack() 恢复原来值
这种方式在VC也支持,从编译器风格上看,应该是GCC兼容VC。设置的n表示的是最大对齐maximum alignment,当比自然对齐的时候,就采用最大对齐;所以,默认情况下最大对齐和最大自然对齐是一致的。
3.2.编译选项
使用GCC提供的编译开关:-fPACK-STRUCT[= ]
3.3.使用__attribute__
主要包含两个算下:pack/aligned;
packed主要是用在结构体的定义上,使用packed后,结构体成员间将不会加入padding;
attribute提高对齐,比如可以定义16个自动的int变量
int x__attribute__ (aligned(16))=0;
aligend与pack联合使用,这样在结构体的最后加入padding。比如:
typedef sturct tagFoo
{
char a;double b;int c;char d;
} __arribute__((aligned(8),packed))Foo;
这个结构体大小是16字节,在最后增加了2个padding。