内存变量边界对齐

Posted shulin~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了内存变量边界对齐相关的知识,希望对你有一定的参考价值。

一、什么是内存对齐

(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\\n",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 }
View Code

(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字节,这样无疑大大降低了程序效率。

以上是关于内存变量边界对齐的主要内容,如果未能解决你的问题,请参考以下文章

使用 GCC/G++/AS 在固定大小的内存边界上对齐本机代码?

内存对齐与页面对齐

内存对齐:C/C++编程中的重要性和技巧

gcc 结构中的内存对齐

C++11:16 字节原子<> 变量是不是在 16 字节边界上自动对齐,允许 CMPXCHG16B 指令?

如何在 C 中分配和释放对齐的内存