講解C語言編程中的結構體對齊
Q:關於結構體的對齊,到底遵循什麼原則?
A:首先先不討論結構體按多少字節對齊,先看看只以1字節對齊的情況:
#include
輸出:
sizeof(student) is 7OFFSET(student,sex) is 0OFFSET(student,score) is 1OFFSET(student,age) is 3
可以看到,如果按1字節對齊,那麼結構體內部的成員緊密排列,sizeof(char) == 1, sizeof(short) == 2, sizeof(int) == 4.
修改上面的代碼, 去掉#pragma pack語句,代碼如下:
#include
運行結果:
sizeof(student) is 8OFFSET(student,sex) is 0OFFSET(student,score) is 2OFFSET(student,age) is 4
此時,各個成員之間就不像之前那樣緊密排列了,而是有一些縫隙。這裏需要介紹下對齊原則:
此原則是在沒有#pragma pack語句作用時的原則(不同平台可能會有不同):
原則A:struct或者union的成員,第一個成員在偏移0的位置,之後的每個成員的起始位置必須是當前成員大小的整數倍;
原則B:如果結構體A含有結構體成員B,那麼B的起始位置必須是B中最大元素大小整數倍地址;
原則C:結構體的總大小,必須是內部最大成員的整數倍;
依據上面3個原則,我們來具體分析下: sex在偏移0處,佔1字節;score是short類型,佔2字節,score必須以2的整數倍為起始位置,所以它的起始位置為2; age為int類型,大小為4字節,它必須以4的整數倍為起始位置,因為前面有sex佔1字節,填充的1字節和score佔2字節,地址4已經是4的整數倍,所以age的位置為4.最後,總大小為4的倍數,不用繼續填充。
繼續修改上面的代碼,增加#pragma pack語句:
#include
運行結果:
sizeof(student) is 8OFFSET(student,sex) is 0OFFSET(student,score) is 2OFFSET(student,age) is 4
具體分析下:
有了#pragma pack(4)語句後,之前説的原則A和C就不適用了。實際對齊原則是自身對齊值(成員sizeof大小)和指定對齊值(#pragma pack指定的對齊大小)的較小者。依次原則,sex依然偏移為0, 自身對齊值為1,指定對齊值為4,所以實際對齊為1; score成員自身對齊值為2,指定對齊值為4,實際對齊為2;所以前面的sex後面將填充一個1字節,然後是score的位置,它的偏移為2;age自身對齊值為4,指定對齊為4,所以實際對齊值為4;前面的sex和score正好佔用4字節,所以age接着存放;它的偏移為4.
Q:關於位域的問題,空域到底表示什麼?
A:它表示之後的位域從新空間開始。
#include
運行結果:
sizeof(bit_info) is 8
bit_info中的a, b佔用4個字節的前4位,到int:0; 時表示此時將填充餘下所有沒有填充的位,即剛剛的4個字節的餘下28位;int d:2; 將從第四個字節開始填充,又會佔用4個字節,所以總大小為8.
再來看下面幾個小例子
例1:
struct A{ char f1 : 3; char f2 : 4; char f3 : 5; };
a b c
A的內存佈局:111,1111 *,11111 * * *
位域類型為char,第1個字節僅能容納下f1和f2,所以f2被壓縮到第1個字節中,而f3只能從下一個字節開始。因此sizeof(A)的結果為2。
例2:
struct B{ char f1 : 3; short f2 : 4; char f3 : 5; };
由於相鄰位域類型不同,在VC6中其sizeof為6,在Dev-C++中為2。
例3:
struct C{ char f1 : 3; char f2; char f3 : 5; };
非位域字段穿插在其中,不會產生壓縮,在VC6和Dev-C++中得到的大小均為3。
考慮一個問題,為什麼要設計內存對齊的`處理方式呢?如果體系結構是不對齊的,成員將會一個挨一個存儲,顯然對齊更浪費了空間。那麼為什麼要使用對齊呢?體系結構的對齊和不對齊,是在時間和空間上的一個權衡。對齊節省了時間。假設一個體繫結構的字長為w,那麼它同時就假設了在這種體系結構上對寬度為w的數據的處理最頻繁也是最重要的。它的設計也是從優先提高對w位數據操作的效率來考慮的。有興趣的可以google一下,人家就可以跟你解釋的,一大堆的道理。
最後順便提一點,在設計結構體的時候,一般會尊照一個習慣,就是把佔用空間小的類型排在前面,佔用空間大的類型排在後面,這樣可以相對節約一些對齊空間。
-
淺談高職C語言課程的教學分析與設計
C語言作為學院網絡技術專業的人門課程,旨在通過鍛鍊學生的邏輯思維,牆養學生在職業崗位中實際應用的能力.目前,該專業的學生畢業後主要從事網站開發和網絡管理等方面的工作,而在這些領域幾乎都以C語言作為應用的開發工具.但從歷年教學實踐來看,教師往往付出的精力多...
-
2017全國計算機二級《C語言》考試題及答案
在備考複習階段,需通過大量試題練習,加深對考點的理解和掌握。以下是本站小編搜索整理的一份全國計算機二級《C語言》考試題及答案,供參考練習,希望對大家有所幫助!想了解更多相關信息請持續關注我們應屆畢業生考試網!一、選擇題1).我們所寫的每條C語句,經過編譯最...
-
C語言新人常見問題與錯誤
不知不覺,學習C語言也快一年了。雖然有C語言課,但是老師完全讓我們自己看書,在自學的過程中,和周圍同學交流中,以及後來在CSDN,BCCN,百度知道看帖回帖中,也看到許多C語言新人常遇到的問題與常犯的錯誤。不妨看看吧。以下僅供參考!對於完整的修正後的程序都在code::block...
-
如何在c語言中調用Linux腳本
如何在c語言中調用Linux腳本呢?你知道如何在c語言中調用Linux腳本嗎?下面是小編為大家帶來的如何在c語言中調用Linux腳本的知識,歡迎閲讀。一、引言對於沒有接觸過Unix/Linux操作系統的人來説,fork是最難理解的概念之一:它執行一次卻返回兩個值。fork函數是Unix系...