【C++ Primer】 神秘的 sizeof(union) 、sizeof(struct) 和記憶體對齊技術

來源:互聯網
上載者:User

一,union:C/C++關鍵字  共用體(聯合)

       共用體的聲明和共用體變數定義與結構十分相似。形式為:

 

union 共用體名{   資料類型 成員名;   資料類型 成員名;   ...   } 變數名; 

       共用體表示幾個變數共用一個記憶體位置,在不同的時間儲存不同的資料類型和不同長度的變數.在union中,所有的共用體成員共用一個空間,並且同一時間只能儲存其中一個成員變數的值。當一個共用體被聲明時, 編譯器自動地產生一個變數, 其長度為聯合中最大的變數長度的整數倍(特別注意數組)

例子一:

 

union foo{

  int i;

  char c;

  double k;

  };

sizeof(foo);   //double最長佔用8位元組,所以union foo大小為8位元組

 

例子二: 

union A  {    int a[5];       //20    short b;     //2    double c;    //8    char p2;     //1};struct B { int n; // 4位元組 A a; // 24位元組 char c[10]; // 10位元組 };

 

 

      sizeof(A) ;  //24     而不是20     ???

      sizeof(B) ;  //48     而不是???

      對齊: 分配記憶體時,每個成員放在長度倍數位置,如果不夠,補位對齊

      補齊: 對整個結構變數的空間要求總長度一定是最長的成員的倍數,不夠補齊不管是對齊還是補齊,最長的成員長度超過4時,以4計。

 

      A實際佔用記憶體大小為 20位元組,但是要跟 8個位元組的變數double的整數倍,對齊所以為 24;

      由於A實際佔用24位元組,則可以想象B實際佔用38位元組,但A是8位元組對齊的,所以int   n和char   c[10]也需要8位元組對齊,總共8+24+16=48 位元組。

      

例子三:

 

union f   {   char s[10];   int i;   };

      sizeof(f);  //  12
      解釋:在這個union中,foo的記憶體空間的長度為12,是int型的3倍,而並不是數組的長度10。
                 若把int改為double,則foo的記憶體空間為16,是double型的兩倍。

二,struct

        具體說明見記憶體對齊例子

 

三,記憶體對齊

       1)概念:“記憶體對齊”應該是編譯器的“管轄範圍”。編譯器為程式中的每個“資料單元”安排在適當的位置上。

       2)原因:

            1、平台原因(移植原因):不是所有的硬體平台都能訪問任意地址上的任意資料的;某些硬體平台只能在某些地址處取某些特定類型的資料,否則拋出硬體異常。   

            2、效能原因:資料結構(尤其是棧)應該儘可能地在常態範圍上對齊。原因是:為了訪問未對齊的記憶體,處理器需要作兩次記憶體訪問;而對齊的記憶體訪問僅需要一次訪問。

       3)對齊規則

      每個特定平台上的編譯器都有自己的預設“對齊係數”(也叫對齊模數)。程式員可以通過先行編譯命令#pragma pack(n),n=1,2,4,8,16來改變這一係數,其中的n就是你要指定的“對齊係數”。   

           規則:   

          1、資料成員對齊規則:結構(struct)(或聯合(union))的資料成員,第一個資料成員放在offset為0的地方,以後每個資料成員的對齊按照#pragma pack指定的數值和這個資料成員自身長度中,比較小的那個進行。   

          2、結構(或聯合)的整體對齊規則:在資料成員完成各自對齊之後,結構(或聯合)本身也要進行對齊,對齊將按照#pragma pack指定的數值和結構(或聯合)最大資料成員長度中,比較小的那個進行。   

         3、結合1、2可推斷:當#pragma pack的n值等於或超過所有資料成員長度的時候,這個n值的大小將不產生任何效果。

 

pragma  pack(1) 時候

 

        1>資料成員對齊:

#pragma pack(1)struct test_t {int a;      /* int型,  長度4 > 1 按1對齊;起始offset=0 0%1=0;存放位置區間[0,3] */char b;     /* char型, 長度1 = 1 按1對齊;起始offset=4 4%1=0;存放位置區間[4] */short c;    /* short型,長度2 > 1 按1對齊;起始offset=5 5%1=0;存放位置區間[5,6] */char d[6];  /* char型, 長度1 = 1 按1對齊;起始offset=7 7%1=0;存放位置區間[7,C] */};/*char d[6]要看成6個char型變數*/

        sizeof(test_t) ;     //輸出為13

        2>整體對齊

       整體對齊係數 = min((max(int,short,char), 1) = 1

       整體大小(size)=$(成員總大小) 按 $(整體對齊係數) 圓整 = 13   /*13%1=0*/

 

pragma pack(2) 時候

       1>成員資料對齊

  

  #pragma pack(2)   struct test_t {       int a; /* int型,長度4 > 2 按2對齊;起始offset=0 0%2=0;存放位置區間[0,3] */       char b; /* char型,長度1 < 2 按1對齊;起始offset=4 4%1=0;存放位置區間[4] */      short c; /* short型,長度2 = 2 按2對齊;起始offset=6 6%2=0;存放位置區間[6,7] */       char d[6]; /* char型,長度1 < 2 按1對齊;起始offset=8 8%1=0;存放位置區間[8,D] */   };  

  成員總大小=14

  2> 整體對齊

  整體對齊係數 = min((max(int,short,char), 2) = 2

  整體大小(size)=$(成員總大小) 按 $(整體對齊係數) 圓整 = 14 /* 14%2=0 */

 

四,終極例子

 

入門例子一:

union A{int t;   //4short m; //2char p;  //1};struct B  {    A a;          //4    double c;    //8    char p2;     //1};

       sizeof(B);  // 24 

       B中採用double長度  8位元組對齊,所以A在結構體B內 變成8位元組。實際B佔用 8+8+1=17。再填充成8的整數倍後位 24位元組 

 

變態例子二:

struct B  {    union A{int t;   //4short m; //2char p;  //1} ;    double c;    //8char p2;     //1};

 

       sizeof(B);  //16

 

如果你的第一反應是24那麼你就躺著中槍了。想想為什麼吧!!

4+8+1=13   最大類型 8的最小倍數為 16

附件:在GCC中範例程式碼

#include "stdio.h"typedef struct  BB {       union AA  //沒有typedef    {          int t;   //4          short m; //2          char p;  //1      } AA;      double c;    //8      char p2;     //1  }BB;   typedef union  A //有typedef    {          int t;   //4          short m; //2          char p;  //1      }A;             typedef   struct   B      {          A a;          //4          double c;    //8          char p2;     //1      }B;            int main()  {      printf("BB:%d\n",sizeof(BB));      printf("B:%d\n",sizeof(B));      return 0;  }

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.