一、什么是内存对齐
(1) 原理
a) 编译器按照成员列表的顺序给每个成员分配内存.
b) 当成员需要满足正确的边界对齐时,成员之间用额外字节填充.
c) 结构体的首地址必须满足结构体中边界要求最为严格的数据类型所要求的地址.
d) 结构体的大小为其最宽基本类型的整数倍.
(2) 程序设计
1 #include<iostream> 2 3 #include<cstdio> 4 5 #include<string> 6 7 using namespace std; 8 9 struct node1 10 11 { 12 13 char c; 14 15 char b; 16 17 int a; 18 19 }n1; 20 21 struct node2 22 23 { 24 25 char c; 26 27 int a; 28 29 char b; 30 31 }n2; 32 33 int main() 34 35 { 36 37 //内存大小 38 39 int size1=sizeof(node1); 40 41 int size2=sizeof(node2); 42 43 printf("%d %d ",size1,size2); 44 45 //具体地址 46 47 //node1 48 49 cout<<(long long)(void*)&n1.c-(long long)(void*)&n1<<endl; 50 51 cout<<(long long)(void*)&n1.b-(long long)(void*)&n1<<endl; 52 53 cout<<(long long)(void*)&n1.a-(long long)(void*)&n1<<endl; 54 55 //node2 56 57 cout<<(long long)(void*)&n2.c-(long long)(void*)&n2<<endl; 58 59 cout<<(long long)(void*)&n2.a-(long long)(void*)&n2<<endl; 60 61 cout<<(long long)(void*)&n2.b-(long long)(void*)&n2<<endl; 62 63 return 0; 64 65 }
(3) 结果
实验显示结果为
(4) 分析
a) node1和node2的成员相同,但成员的顺序不一样,所以总体占用的空间不一样,验证了编译器按照成员列表的顺序给每个成员分配内存。
b) 对于node1和node2,分别输出每个成员的占用空间,发现char c和char b顺序紧挨时,各占据一个字节;char a 和char b相隔时,各占据4个字节。验证了当成员需要满足正确的边界对齐时,成员之间用额外字节填充.
c) 实验表明,内存变量是按边界对齐。
二、为什么要按边界对齐(转载请注明出处:http://blog.csdn.net/acs713/article/details/25040389)
从处理器的角度来看,需要尽可能减少对内存的访问次数以实现对数据结构进行更加高效的操作。为什么呢?因为尽管处理器包含了缓存,但它在处理数据时还得读取缓存中的数据,读取缓存的次数当然是越少越好!如上图所示,在采用边界对齐的情况下,当处理器需要访问a_变量和b_变量时都只需进行一次存取(图中花括号表示一次存取操作)。若不采用边界对齐,a_变量只要一次处理器操作,而b_变量却至少要进行两次操作。对于b_,处理器还得调用更多指令将其合成一个完整的4字节,这样无疑大大降低了程序效率。