程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> 關於C >> 關於C語言中結構體中的結構體成員導致的字節對齊問題

關於C語言中結構體中的結構體成員導致的字節對齊問題

編輯:關於C
關於結構體的字節對齊是什麼,就不贅述,再此附上一篇文章,介紹字節對齊:http://www.linuxsong.org/2010/09/c-byte-alignment/   這裡的結構體字節對齊的數據類型都是基本數據類型,如果結構體的定義中含有結構體成員呢?   網上有很多人寫博客談到這個問題,都認為該結構體成員應該被看做一個整體,按照整體的字節數來進行字節對齊,選擇首地址。但是經過測試,這種說法是不對的。   復制代碼  1 struct s1{  2    char c1;  3    char c2;  4    char c3;  5    char c4;   6 };  7   8 struct s2{  9     char a; 10     struct s1 s; 11 }; 復制代碼 對於上述代碼,顯然sizeof(struct s1) = 4。如果將struct s1看做整體,來進行字節對齊的話,sizeof(struct s2)應該是等於8。但是該段代碼在gcc和VS2010下測試的結果都是5。   所以,s2的內存布局如下   s2 : char | char char char char |   s的首地址並非為4,而是char類型長度的整數倍   同樣,對於結構體:   復制代碼  1 struct S1  2 {  3     char a;  4     short b;  5 };  6   7 struct S2  8 {  9     char a; 10     struct S1 s; 11 }; 復制代碼 上述代碼中,sizeof(struct S1) = 4,而sizeof(struct S2) = 6。   S2的內存布局是:   S2 : char **** | char **** short short   s的首地址並非為4,而是short類型長度的整數倍,結構體S2的長度並非結構體S1長度的整數倍,而是short類型長度的整數倍   相對的,我們可以看一下結構體:   struct S {     char a;     char b;     short c; }; sizeof(S) = 4。   其內存布局為:   S : char char short short   對比S2和S,我們看到,S2中的s結構體成員確實是仍按它作為S1結構體的整體(占用4個字節)來布局的。       那麼我們可以得出這情形下的字節對齊問題的結論:   1)結構體中的結構體成員,是按照原結構體的內存布局在新結構體中進行布局的;   2)結構體中的結構體成員,其內存首地址為該成員中最長數據類型的整數倍;   3)結構體的整體長度與其中的結構體成員無關,而是整個結構體(包括結構體成員內部)中的最長數據類型的整數倍。       得出結論後,我們回到處理器本身,來探討一下編譯器之所以這麼處理的原因。   從CPU結構角度看內存對齊有一篇比較易懂的文章:   http://hi.baidu.com/maikeai/item/4976f24cc0f905d3c1a592a0   從該文章中,我們可以知道,之所以需要內存對齊,是CPU為了讀取數據時減少讀取存儲器的次數,提高效率。   對於32位的CPU,一次最多讀入雙字的32位數據,而對於超過32位的數據,在32位的計算機上,就必須多次讀取存儲器,這與是否字節對齊無關。   我們可以看到,字節對齊,其實實質上是在拿存儲器的空間,換CPU的時間。   所以,對於C語言內置的數據類型,可以很好地通過內存對齊來節省時間,同時其浪費的存儲器空間也是可控的。   但是,對於結構體成員來說,因為它的長度是不可控的,所以如果強行按整體內存對齊,首先可能因為長度過長,即使內存對齊需要的存儲器讀取次數也很多,導致優化的時間不明顯,另外,也可能導致浪費的存儲器空間太大。所以,最簡單的平衡空間和時間的方法,就是按照該結構體成員中最長數據類型來進行字節對齊,這樣最有可能減少存儲器讀取次數,也使浪費的存儲器空間可控。
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved