谈内存对齐

来源:互联网 发布:80c51单片机引脚功能 编辑:程序博客网 时间:2024/05/21 07:13

http://blog.csdn.net/seanyxie/article/details/6176145

以前总以为内存对齐,固定的是以4个字节为单位的,今天发现原来错了...

很早之前写过一篇简单的http://blog.csdn.net/xie376450483/archive/2010/05/24/5620696.aspx

为什么要内存对齐呢

  大部分的参考资料都是如是说的:

  1、平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。

  2、性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

 

首先来看一个例子

[cpp] view plaincopyprint?
  1. #include <iostream>  
  2. using namespace std;  
  3. class A1  
  4. {  
  5.     short a;  
  6.     char c;  
  7. };  
  8.   
  9. void main()  
  10. {  
  11.     cout<<sizeof(A1)<<endl;  
  12. }  

结果是4,

原因是当结构体或者类内部的最大的元素的长度小于处理器的位数时候,便以结构体内长度最长的那个也元素为对齐单位,这里最长的是short,两个字节,所以第二个char其实也想当于占了两个字节,这样一来就占了四个字节

当然我们也可以通过#pragma pack(n)  来修改对齐系数,这里的n是1,2,4,8等

如果在上例中添加上

#pragma pack(1)

那么结果就成了3

 

在看下面的这个例子

[cpp] view plaincopyprint?
  1. #include <iostream>  
  2. using namespace std;  
  3. class A1  
  4. {  
  5.     short a;  
  6.     int b;  
  7.     char c;  
  8. };  
  9.   
  10. void main()  
  11. {  
  12.     cout<<sizeof(A1)<<endl;  
  13. }  

根据我们刚才学到的内存对齐原则,很明显结果是12

但是我们在开始加上这一句呢

#pragma pack(8)

结果会不会变成16呢,答案是否定的,因为当pack里面的n值大于结构体内所有元素的长度时候,prama pack(n)就不起作用了

 

 

和内存对齐类似的是数据对齐

所谓数据对齐,是指数据所在的位置必须是该数据长度的整数倍,DWORD数据的内存起始地址能被4整除,WORD数据能被2整除  x86 CPU能直接访问一个对齐的数据,如果一个数据没有对齐,会在内部进行一系列的调整

 

 

[cpp] view plaincopyprint?
  1. void main()  
  2. {  
  3.     int a;  
  4.     short d;  
  5.     int c;  
  6.     cout<<&a<<endl;  
  7.     cout<<&d<<endl;  
  8.     cout<<&c<<endl;  
  9. }  

看输出结果

 

 



在实现了内存对齐之后,还要考虑结构体边界对齐。必须要是最大偏移量的倍数。还有带虚函数的类。

0 0
原创粉丝点击