C語言中結構體大小計算即存儲分配

C語言中常用預定義的數據類型:

類型:         char short int long float double (long double)

大小(字節數):

  gcc3.2.2: 1      2    4   4     4     8      12

  Visual C++:1      2    4   4     4     8      8

ARM架構下被訪問的變量大小形式可以爲32位(字)、16位(半字)、8位(字節),當然,還有bit原子位操作。

typedef signed long  s32;
typedef signed short s16;
typedef signed char  s8;

typedef unsigned long  u32;
typedef unsigned short u16;
typedef unsigned char  u8;

定義一個結構體類型的時候(這裏是定義結構體類型struct StrucTypeDef,不是定義一個結構體變量struct StrucTypeDef stru1或者結構體指針struct StrucTypeDef *stru2)並沒有分配實際的地址空間(定義結構體變量在編譯鏈接過程中給了實際地址,而結構體指針要顯式的用malloc等形式申請棧內地址),通俗的說就是定義類型是沒有實際分配空間的,而定義變量的時候會分配空間。

以下內容編輯前轉自http://blog.csdn.net/lichunming83/archive/2009/10/31/4752818.aspx

Win32平臺下的微軟C編譯器(cl.exe for 80×86)的對齊策略:

1) 結構體變量的首地址是其最長基本類型成員的整數倍;

備註:編譯器在給結構體開闢空間時,首先找到結構體中最寬的基本數據類型,然後尋找內存地址能是該基本數據類型的整倍的位置,作爲結構體的首地址。將這個最寬的基本數據類型的大小作爲上面介紹的對齊模數。

2) 結構體每個成員相對於結構體首地址的偏移量(offset)都是成員大小的整數倍,如有需要編譯器會在成員之間加上填充字節(internal adding);

備註:爲結構體的一個成員開闢空間之前,編譯器首先檢查預開闢空間的首地址相對於結構體首地址的偏移是否是本成員的整數倍,若是,則存放本成員,反之,則在本成員和上一個成員之間填充一定的字節,以達到整數倍的要求,也就是將預開闢空間的首地址後移幾個字節。

3) 結構體的總大小爲結構體最寬基本類型成員大小的整數倍,如有需要,編譯器會在最末一個成員之後加上填充字節(trailing padding)。

備註:結構體總大小是包括填充字節,最後一個成員滿足上面兩條以外,還必須滿足第三條,否則就必須在最後填充幾個字節以達到本條要求。

 4) 結構體內類型相同的連續元素將在連續的空間內,和數組一樣。

5) 如果結構體內存在長度大於處理器位數的元素,那麼就以處理器的倍數爲對齊單位;否則,如果結構體內的元素的長度都小於處理器的倍數的時候,便以結構體裏面最長的數據元素爲對齊單位。

 

以下內容編輯前轉自http://www.dzsc.com/data/html/2009-6-4/76676.html

運算符sizeof可以計算出給定類型的大小,對於32位系統來說,sizeof(char) = 1; sizeof(int) = 4。基本數據類型的大小很好計算,我們來看一下如何計算構造數據類型的大小。

  C語言中的構造數據類型有三種:數組、結構體和共用體。

  數組是相同類型的元素的集合,只要會計算單個元素的大小,整個數組所佔空間等於基礎元素大小乘上元素的個數。

  結構體中的成員可以是不同的數據類型,成員按照定義時的順序依次存儲在連續的內存空間。和數組不一樣的是,結構體的大小不是所有成員大小簡單的相加,需要考慮到系統在存儲結構體變量時的地址對齊問題。看下面這樣的一個結構體:

  struct stu1

  {

  int i;

  char c;

  int j;

  };

  先介紹一個相關的概念——偏移量。偏移量指的是結構體變量中成員的地址和結構體變量地址的差。結構體大小等於最後一個成員的偏移量加上最後一個成員的大小。顯然,結構體變量中第一個成員的地址就是結構體變量的首地址。因此,第一個成員i的偏移量爲0。第二個成員c的偏移量是第一個成員的偏移量加上第一個成員的大小(0+4),其值爲4;第三個成員j的偏移量是第二個成員的偏移量加上第二個成員的大小(4+1),其值爲5。

  實際上,由於存儲變量時地址對齊的要求,編譯器在編譯程序時會遵循兩條原則:一、結構體變量中成員的偏移量必須是成員大小的整數倍(0被認爲是任何數的整數倍)二、結構體大小必須是所有成員大小的整數倍。

  對照第一條,上面的例子中前兩個成員的偏移量都滿足要求,但第三個成員的偏移量爲5,並不是自身(int)大小的整數倍。編譯器在處理時會在第二個成員後面補上3個空字節,使得第三個成員的偏移量變成8。

  對照第二條,結構體大小等於最後一個成員的偏移量加上其大小,上面的例子中計算出來的大小爲12,滿足要求。

  再看一個滿足第一條,不滿足第二條的情況

  struct stu2

  {

  int k;

  short t;

  };

  成員k的偏移量爲0;成員t的偏移量爲4,都不需要調整。但計算出來的大小爲6,顯然不是成員k大小的整數倍。因此,編譯器會在成員t後面補上2個字節,使得結構體的大小變成8從而滿足第二個要求。由此可見,大家在定義結構體類型時需要考慮到字節對齊的情況,不同的順序會影響到結構體的大小。對比下面兩種定義順序

  struct stu3

  {

  char c1;

  int i;

  char c2;

  }

  struct stu4

  {

  char c1;

  char c2;

  int i;

  }

  雖然結構體stu3和stu4中成員都一樣,但sizeof(struct stu3)的值爲12而sizeof(struct stu4)的值爲8。

  如果結構體中的成員又是另外一種結構體類型時應該怎麼計算呢?只需把其展開即可。但有一點需要注意,展開後的結構體的第一個成員的偏移量應當是被展開的結構體中最大的成員的整數倍。看下面的例子:

  struct stu5

  {

  short i;

  struct

  {

  char c;

  int j;

  } ss;

  int k;

  }

  結構體stu5的成員ss.c的偏移量應該是4,而不是2。整個結構體大小應該是16。

  如何給結構體變量分配空間由編譯器決定,以上情況針對的是Linux下的GCC。其他平臺的C編譯器可能會有不同的處理。

 

PS:這篇寫的確實不錯,很詳細,我這裏推薦一下其他的一些好的資料  可以繼續學習:

頂嵌的培訓資料: http://learn.akae.cn/media/ch19s04.html 

其他資料我就不多說了 資料太多了  好不好就看你怎麼看待和利用了  不能全信但不能不信 實踐是真理。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章