#pragma pack的使用

#pragma pack的作用

程序编译器对变量的存储带有一定随机性,而pragma pack是一种字节对齐方法,采用人为设定的方式将存储数据按一定格式排布。百科中提到了其一种作用:有的平台每次读都是从偶地址开始,如果一个int型存放在偶地址开始处,一个读周期就可以读出,如果存在奇地址开始处,则需要两个周期,并且需要对读出结果高低字节进行拼凑,降低了读取效率。因此对于这种平台人为对齐数据在偶地址开头处是有必要的。因为刚接触,我目前感觉其最大作用就是数据整齐排布后它们的地址排布也十分清晰(尤其是较为复杂固定数据结构),知道一个数据的地址可以推算出其他数据地址,不用再每次都去取地址。
 
#pragma pack的使用方法
百科里写的比较复杂,其实一般用起来也就设置一个对齐长度就行了,即:
  1.  
    #pragma pack(n) //开始对齐,n是对齐长度
  2.  
    {
  3.  
    此部分定义的数据进行对齐
  4.  
    }
  5.  
    #pragma pack () //取消对齐
#pragma pack对齐数据结构大小的计算方法
网上有的写的比较复杂,我就总结一下:
(1)首先,实际对齐长度不一定是你设置的对齐长度,应该是实际对齐长度=min(设置对齐长度,数据的最长长度)。什么意思,举个例子,你设置对齐长度为4,你的数据中包括int型(长度4),那对齐长度就是4;如果你的数据中仅有short(长度2),那么对齐长度就是2,为什么是这样可以仔细琢磨一下。
(2)保证每一个数据满足:  不同类型数据都满足:  首地址%数据长度 = 0 
(3)补齐末尾的空间,保证长度对齐,即总长度%实际对齐长度=0
 
以上有点抽象,举几个例子:
  1.  
    #pragma pack(4)
  2.  
    struct test1
  3.  
    {
  4.  
    int a;
  5.  
    char b;
  6.  
    short c;
  7.  
    char d;
  8.  
    };
  9.  
     
  10.  
    #pragma pack ()
(1)数据中最长为int(长度4),设置对齐长度4,因此实际对齐长度4
(2)int首地址0,长度4,0%4=0,没问题,占据[0,3];char首地址4,长度1,4%1=0没问题,占据[4];short首地址5,长度2,5%2!=0,因此不行,此处要补空位,short首地址为6,6%2=0,没问题了,占据[6,7];char首地址8,长度1,8%1=0没问题,占据[8]。
(3)最后补齐,[9,10,11],使得12%4=0。
因此 sizeof(test1) =12。
  1.  
    #pragma pack(2)
  2.  
    struct test2
  3.  
    {
  4.  
    int a;
  5.  
    char b;
  6.  
    short c;
  7.  
    char d;
  8.  
    };
  9.  
     
  10.  
    #pragma pack ()

这个例子与上一个类似,值得注意的是设置对齐长度为2。按照取最小原则,实际对齐长度为2,因此第三步中10%2=0,即sizeof(test2)=10。

  1.  
    #pragma pack(4)
  2.  
    struct test3
  3.  
    {
  4.  
    char b;
  5.  
    short c;
  6.  
    char d;
  7.  
    };
  8.  
     
  9.  
    #pragma pack ()
在这个例子中,去掉了整形int,因此数据中最大长度为2(short),即使设置了对齐长度为4,实际对齐长度仍为2。通过以上步骤可以得到sizeof(test3)=6。
posted @ 2019-03-25 16:50  L像疯了一样  Views(2101)  Comments(0Edit  收藏  举报