C語言 sizeof計算結(jié)構(gòu)體大小
通常提到sizeof()就會想到煩人的:
關(guān)于sizeof()和strlen()的區(qū)別,有一大堆.
這里網(wǎng)上資料比較全,暫且放一放.

這一節(jié)介紹sizeof計算結(jié)構(gòu)體大小:

為什么會是6呢?
大家都知道結(jié)構(gòu)體在計算機中是按照定義時的順序依次存儲在連續(xù)的內(nèi)存空間,
但是結(jié)構(gòu)體的大小并不是簡單相加,
需要考慮地址對齊問題。
結(jié)構(gòu)體大小計算方法是,最后一個成員的偏移量加上其大小。
想象一個長條的緩存中,比如注射器,偏移量就有點像緩存中的活塞位置.
最后一個成員的偏移量,就是之前的成員所占內(nèi)存和.加上最后一個成員的大小.
1,偏移量的計算也需要技巧,
需要滿足:是成員大小的整數(shù)倍.
2,最后結(jié)構(gòu)體的大小必須是所有成員的整數(shù)倍.
如果不滿足上面兩條,就需要對大小進(jìn)行即時調(diào)整.使其滿足上面條件.

比如上面例子中:
從a開始算,如果st結(jié)構(gòu)體中只有a,那么st結(jié)構(gòu)體的大小就是:
到a的偏移量0 + a的大小1 =1個字節(jié).
如果st結(jié)構(gòu)體中有a,b兩個變量就是:
到b的偏移量,即(a占用的1)? + b的大小2? = 3個字節(jié)?? (這里是錯的 )
b的偏移量本來應(yīng)該是1,但是,不滿足前面的約束條件:
b的偏移量必須是b的整數(shù)倍,但是現(xiàn)在不滿足了,1不是2的整數(shù)倍.所以需要調(diào)整偏移量.
那么b的偏移量就是從1->2,這樣就可以了.
所以,到b處結(jié)構(gòu)體st占用:
到b的偏移量(調(diào)整后占2)+b的大小(2) = 4個字節(jié). (這里正確)
現(xiàn)在st有三個變量,a,b,c,所以還需要計算c.
到c處的偏移量是4,c占1,(此處是滿足的,偏移量是成員的整數(shù)倍,即4是1的整數(shù)倍).
那么接著向下計算,
結(jié)構(gòu)體st的大小:
到c的偏移量(4)+c的大小(1) = 5個字節(jié).(這里是錯的 )
但是這里是錯的.因為5不滿足上面的第二個條件,結(jié)構(gòu)體的大小不是成員的整數(shù)倍.
5不是b(占2)的整數(shù)倍,所以,要調(diào)整結(jié)構(gòu)體大小,讓他滿足.
所以從5調(diào)整到了6就可以了.
到c的偏移量(4)+c的大小(1) = 5個字節(jié)(調(diào)整到6).? (這里是正確的)
所以最終結(jié)果是6

編譯器提供了一種字節(jié)對齊的方式
#pragma pack(1)? // 指定對齊
#pragma pack()??? // 取消指定對齊
這兩個通常是成對出現(xiàn),放在結(jié)構(gòu)體前后,用于偏移量的調(diào)整.
比如還是上面的例子,加入指定對齊之后:(結(jié)構(gòu)體大小由原來的6變成了4.)

之所以由原來的6變成了4,
是因為#pragma pack(1)的作用,
它是為了讓每個成員存儲的起始位置發(fā)生變化.
比如上面沒有加#pragma pack(1)之前.
計算結(jié)構(gòu)體a,b占用大小時,b必須距離a 2個字節(jié).
但是如果加了#pragma pack(1),因為傳入?yún)?shù)是1,那么b既可以緊貼著a開始存儲了.不用再考慮條件1中,偏移量是成員大小的整倍數(shù)了.