** :
請看下面的結構:
struct mystruct ;
對結構mystruct採用sizeof會出現什麼結果呢?sizeof(mystruct)為多少呢?
也許你會這樣求:sizeof(mystruct)=sizeof(double)+sizeof(char)+sizeof(int)=13
但是當在vc中測試上面結構的大小時,你會發現sizeof(mystruct)為16。你知道為什麼在vc中會得出這樣乙個結果嗎?
其實,這是vc對變數儲存的乙個特殊處理。為了提高cpu的儲存速度,vc對一些變數的起始位址做了「對齊」處理。在預設情況下,vc規定各成員變數存放的起始位址相對於結構的起始位址的偏移量必須為該變數的型別所占用的位元組數的倍數。下面列出常用型別的對齊方式(vs6.0 &vs8.0,32位系統)。
型別對齊方式(變數存放的起始位址相對於結構的起始位址的偏移量)
char
偏移量必須為sizeof(char)即1的倍數
short
偏移量必須為sizeof(short)即2的倍數
int
偏移量必須為sizeof(int)即4的倍數
float
偏移量必須為sizeof(float)即4的倍數
double
偏移量必須為sizeof(double)即8的倍數
各成員變數在存放的時候根據在結構中出現的順序依次申請空間,同時按照上面的對齊方式調整位置,空缺的位元組vc會自動填充。同時vc為了確保結構的大小為結構的位元組邊界數(即該結構中占用最大空間的型別所占用的位元組數)的倍數,所以在為最後乙個成員變數申請空間後,還會根據需要自動填充空缺的位元組。
下面用前面的例子來說明vc到底怎麼樣來存放結構的。
struct mystruct ;
為上面的結構分配空間的時候,vc根據成員變數出現的順序和對齊方式,依次分配。
(1)先為第乙個成員dda1分配空間,其起始位址跟結構的起始位址相同,剛好偏移量0剛好為
sizeof(double)的倍數,該成員變數占用sizeof(double)=8個位元組;
(2)接下來為第二個成員dda分配空間,這時下乙個可以分配的位址對於結構的起始位址的偏移量
為8,是sizeof(char)的倍數,所以把dda存放在偏移量為8的地方滿足對齊方式,該成員變數佔
用sizeof(char)=1個位元組;
(3) 接下來為第三個成員type分配空間,這時下乙個可以分配的位址對於結構的起始位址的偏移
量為9,不是sizeof(int)=4的倍數,為了滿足對齊方式對偏移量的約束問題,vc自動填充3個字
節(這三個位元組沒有放什麼東西),這時下乙個可以分配的位址對於結構的起始位址的偏移量為12,
剛好是=4的倍數,所以把type存放在偏移量為12的地方,該成員變數占用sizeof(int)=4個位元組;
(4) 這時整個結構的成員變數已經都分配了空間,總的占用的空間大小為:8+1+3+4=16,剛好為
結構的位元組邊界數(即結構中占用最大空間的型別所占用的位元組數sizeof(double)=8)的倍數,所
以沒有空缺的位元組需要填充。
(5) 所以整個結構的大小為:sizeof(mystruct)=8+1+3+4=16,其中有3個位元組是vc自動填充的,沒
有放任何有意義的東西。
下面再舉個例子,交換一下上面的mystruct的成員變數的位置,使它變成下面的情況:
struct mystruct ;
這個結構占用的空間為多大呢?在vc6.0環境下,可以得到sizeof(mystruc)為24。結合上面提到的分配空間的一些原則,分析下vc怎麼樣為上面的結構分配空間的。(簡單說明)
struct mystruct ;
所有成員變數都分配了空間,空間總的大小為1+7+8+4=20,不是結構的節邊界數(即結構中占用最大空間的型別所占用的位元組數sizeof(double)=8)的倍數,所以需要填充4個位元組,以滿足結構的大小為sizeof(double)=8的倍數。
所以該結構總的大小為:sizeof(mystruc)為1+7+8+4+4=24。其中總的有7+4=11個位元組是vc自動填充的,沒有放任何有意義的東西。
vc對結構的儲存的特殊處理確實提高cpu儲存變數的速度,但是有時候也帶來了一些麻煩,我們也遮蔽掉變數預設的對齊方式,自己可以設定變數的對齊方式。
vc中提供了#pragma
pack(n)來設定變數以n位元組對齊方式。n位元組對齊就是說變數存放的起始位址的偏移量有兩種情況:第
一、如果n大於等於該變數所占用的位元組數,那麼偏移量必須滿足預設的對齊方式,第
二、如果n小於該變數的型別所占用的位元組數,那麼偏移量為n的倍數,不用滿足預設的對齊方式。結構的總大小也有個約束條件,分下面兩種情況:如果n大於所有成員變數型別所占用的位元組數,那麼結構的總大小必須為占用空間最大的變數占用的空間數的倍數;否則必須為n的倍數。下面舉例說明其用法。
#pragma
pack(push) //
儲存對齊狀態
#pragma
pack(4)//
設定為4位元組對齊
struct test;
#pragma
pack(pop)//
恢復對齊狀態
以上結構的大小為16,下面分析其儲存情況,首先為m1分配空間,其偏移量為0,滿足我們自
己設定的對齊方式(4位元組對齊),m1占用1個位元組。接著開始為m4分配空間,這時其偏移量為1,
需要補足3個位元組,這樣使偏移量滿足為n=4的倍數(因為sizeof(double)大於n),m4占用8個位元組。
接著為m3分配空間,這時其偏移量為12,滿足為4的倍數,m3占用4個位元組。這時已經為所有成
員變數分配了空間,共分配了16個位元組,滿足為n的倍數。如果把上面的#pragma pack(4)改為
#pragma pack(16),那麼我們可以得到結構的大小為24。(請讀者自己分析)
參考:msdn關於sizeof的定義:
《vc中的sizeof的用法總結》
《什麼是記憶體對齊》
sizeof struct 大小討論
2009 11 08 14 05 51 分類 c語言雜記 舉報 字型大小 訂閱 struct 結構大小和順序 progma pack引數有關係 針對位元組對齊,環境使用的gcc version 3.2.2編譯器 32位x86平台 為例。char 長度為1個位元組,short 長度為2個位元組,int...
sizeof struct 大小討論
struct 結構大小和順序 progma pack引數有關係 針對位元組對齊,環境使用的 gcc version 3.2.2 編譯器 32位 x86平台 為例。char 長度為1個位元組,short 長度為2個位元組,int 長度為4個位元組。struct 子項在記憶體中的按順序排列,在沒有 pr...
sizeof(struct)對齊方式
結構體是一種復合資料型別,通常編譯器會自動的進行其成員變數的對齊,已提高資料訪問的效率。在預設情況下,編譯器為結構體的成員按照自然對齊 natural alignment 條方式分配儲存空間,各個成員按照其宣告順序在儲存器中順序儲存。自然對齊是指按照結構體中成員size最大的對齊,在cl編譯器下可以...