内存字节对齐

来源:互联网 发布:软件设计方案模板 编辑:程序博客网 时间:2024/06/06 02:12

最近找工作,老是出现类似sizeof(struct)的笔试题,以为很简单···后来才发现里面有奥妙,废话不多说,以下是总结的几位牛人博客的解释。

一、概念

对齐跟数据在内存中的位置有关。如果一个变量的内存地址正好位于它长度的整数倍,他就被称做自然对齐。比如在32位cpu下,假设一个整型变量的地址为0x00000004,那它就是自然对齐的。

二、为什么要字节对齐

需要字节对齐的根本原因在于CPU访问数据的效率问题。假设上面整型变量的地址不是自然对齐,比如为0x00000002,则CPU如果取它的值的话需要访问两次内存,第一次取从0x00000002-0x00000003的一个short,第二次取从0x00000004-0x00000005的一个short然后组合得到所要的数据,如果变量在0x00000003地址上的话则要访问三次内存,第一次为char,第二次为short,第三次为char,然后组合得到整型数据。而如果变量在自然对齐位置上,则只要一次就可以取出数据。一些系统对对齐要求非常严格,比如sparc系统,如果取未对齐的数据会发生错误,举个例:  

char ch[8]={0};char *p = &ch[1];int i=*(int *)p;cout<<" i = "<<i<<endl;

  运行时会报segment error,而在x86上就不会出现错误,只是效率下降。

三、对齐规则

    1、数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储。

2:结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储.(struct a里存有struct b,b里有char,int ,double等元素,那b应该从8的整数倍开始存储.)

3:收尾工作:结构体的总大小,也就是sizeof的结果,.必须是其内部最大成员的整数倍.不足的要补齐.


测试:

#include <iostream>using namespace std;typedef struct bb{int intID;  // 0-3double doubleID;//8-15 规则1float floatID;  //16-19   总长度为24  规则3}BB_struct;typedef struct aa{char charID[2];  //0-1int intID;       //4-7 规则1double doubleID; //8-15 short shortID;   //16 -17BB_struct bb_ID;  //24-47 规则3}AA_struct;int main(){char ch[8]={0};char *p = &ch[1];int i=*(int *)p;cout<<" i = "<<i<<endl;cout<<"-------基本数据类型大小-------"<<endl;cout<<"The size of int : "<<sizeof(int)<<endl;cout<<"The size of double : "<<sizeof(double)<<endl;cout<<"The size of float : "<<sizeof(float)<<endl;cout<<"The size of short : "<<sizeof(short int)<<endl;cout<<"-------结构体大小------"<<endl;cout<<"Struct BB's size is : "<<sizeof(BB_struct)<<endl;cout<<"Struct AA's size is : "<<sizeof(AA_struct)<<endl;return 0;}


四、深入:#pragma pack() 的作用 

在上述代码前加上一行: #pragma pack(1) ,可以告诉编译器,对结构体作1字节对齐。至于#pragma pack(2)、 #pragma pack(3)请大家自己测试!


参考文献:

http://blog.csdn.net/21aspnet/article/details/6729724/

http://blog.csdn.net/hairetz/article/details/4084088

0 0
原创粉丝点击