結構體與位域的對齊

C結構體和C++中的類極爲相似 它也可以有構造和析構函數以及其他成員函數 成員函數也通過一個隱含的this指針來操作類成員 它們之間唯一的區別就是默認的成員訪問權限 類是私有 結構體是公有 以下對結構體的對齊操作等 大多數也對C++類適用

     結構體的對齊方式;
          1.對於結構體中的成員 每一個成員的地址必須是該成員類型大小的整數倍
          如
          
          
          編譯器這樣對齊是爲了能夠更高效率的傳輸數據 但是這樣也會有一些問題 比如我們將結構體裏的數據不變
      但是改變它們的順序:
         
          此時結構體的大小變爲了8 比前面節省了四個字節 也就是說結構體中的成員按照類型從小到大的序列是最好的 可惜編譯器不會爲我們做這些 
          結構體成員的對齊方式使得我們在使用時要注意以下幾點:
               同一個結構體成員定義順序不同 得到的大小可能不同
               結構體中中的成員有自己的對齊方式 因此我們不應該有通過*(&(s.a)+1)來訪問b等類似的操作
               如果結構體ST含有靜態成員 那麼靜態成員長度將不包含在sizeof(s)中 (類似C++中靜態成員屬於類)
     2.結構體的對齊方式,結構體的對齊字節就是結構體中最長的成員類型長度
               如對於上面定義的ST 它按照四個字節對齊
               又如:
     
          
          ST按照其中類型最長的double8字節對齊 這可以在STT中驗證(stt.s1地址最後一位爲0 是8的倍數) 
          STT包含ST STT的類型對齊將按照結構體ST的對齊方式 即也爲8字節 可以在STTT中驗證(&sttt.s2最後一位爲8)
          另外 對於空結構體 它也要佔用一個字節的內存 因爲編譯器要確保每一個結構體都有唯一的地址 注意這一個字節的空間在棧中由於棧本身的對齊方式 將佔用四個字節

     位域:
          位域是指爲位爲單位來定義某結構體的成員變量 它和結構體是分不開的
          
           可見 a b c三個位段共用一個地址 但是變量i仍然其類型int的對齊方式 abc一共9位 剩餘的23位並未使用
          位域的一些使用:
          1.位域變量僅限整型
          2.位域變量的長度不能夠超過其本身類型的長度
          3.如果某一位域要從一個新的類型對齊處開始 可以在前面加一個長度爲0的匿名位域 unsigned :0
          4.匿名位域長度不爲0時 只起佔位的作用
          5.一個位域必須容納在同一個其類型對齊長度內
          關於位域對齊更多資料(網上摘錄):


          /*************************************************************************

                    C99規定int、unsigned int和bool可以作爲位域類型,但編譯器幾乎都對此作了擴展,
                    允許其它類型類型的存在。
                    使用位域的主要目的是壓縮存儲,其大致規則爲:
                    1) 如果相鄰位域字段的類型相同,且其位寬之和小於類型的sizeof大小,則後面的字段將緊鄰前一個字段存儲,直到不能容納爲止;
                    2) 如果相鄰位域字段的類型相同,但其位寬之和大於類型的sizeof大小,則後面的字段將從新的存儲單元開始,其偏移量爲其類型大小的整數倍;(經測試此條好像僅限於char型,整型可以跨域存儲)
                    3) 如果相鄰的位域字段的類型不同,則各編譯器的具體實現有差異,VC6採取不壓縮方式,Dev-C++採取壓縮方式;
                    4) 如果位域字段之間穿插着非位域字段,則不進行壓縮;
                    5) 整個結構體的總大小爲最寬基本類型成員大小的整數倍。
***************************************************************************/

               struct s1 
               { 
               int i: 8; 
               int j: 4; 
               int a: 3; 
               double b; 
               }; 

               struct s2 
               { 
               int i: 8; 
               int j: 4; 
               double b; 
               int a:3; 
               }; 

               printf("sizeof(s1)= %d\n", sizeof(s1)); 
               printf("sizeof(s2)= %d\n", sizeof(s2)); 
               result: 16, 24 
               第一個結構體中,i,j,a共佔15個位,不足8個字節,按double 8字節對齊,共16字節

       第二個結構體中,i,j共佔12位,不足8字節,按8字節對齊,a也按8字節對齊,加上double共8+8+8=24個字節
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章