亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

【轉載】結構體字節對齊

2019-11-10 17:13:51
字體:
來源:轉載
供稿:網友

作者:海子      出處:http://www.cnblogs.com/dolphin0520/      本博客中未標明轉載的文章歸作者海子和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。

結構體字節對齊 在用sizeof運算符求算某結構體所占空間時,并不是簡單地將結構體中所有元素各自占的空間相加,這里涉及到內存字節對齊的問題。從理論上講,對于任何變量的訪問都可以從任何地址開始訪問,但是事實上不是如此,實際上訪問特定類型的變量只能在特定的地址訪問,這就需要各個變量在空間上按一定的規則排列,而不是簡單地順序排列,這就是內存對齊。 內存對齊的原因: 1)某些平臺只能在特定的地址處訪問特定類型的數據; 2)提高存取數據的速度。比如有的平臺每次都是從偶地址處讀取數據,對于一個int型的變量,若從偶地址單元處存放,則只需一個讀取周期即可讀取該變量;但是若從奇地址單元處存放,則需要2個讀取周期讀取該變量。

  在C99標準中,對于內存對齊的細節沒有作過多的描述,具體的實現交由編譯器去處理,所以在不同的編譯環境下,內存對齊可能略有不同,但是對齊的最基本原則是一致的,對于結構體的字節對齊主要有下面兩點:    1)結構體每個成員相對結構體首地址的偏移量(offset)是對齊參數的整數倍,如有需要會在成員之間填充字節。編譯器在為結構體成員開辟空間時,首先檢查預開辟空間的地址相對于結構體首地址的偏移量是否為對齊參數的整數倍,若是,則存放該成員;若不是,則填充若干字節,以達到整數倍的要求。    2)結構體變量所占空間的大小是對齊參數大小的整數倍。如有需要會在最后一個成員末尾填充若干字節使得所占空間大小是對齊參數大小的整數倍。   注意:在看這兩條原則之前,先了解一下對齊參數這個概念。對于每個變量,它自身有對齊參數,這個自身對齊參數在不同編譯環境下不同。下面列舉的是兩種最常見的編譯環境下各種類型變量的自身對齊參數

  從上面可以發現,在windows(32)/VC6.0下各種類型的變量的自身對齊參數就是該類型變量所占字節數的大小,而在linux(32)/GCC下double類型的變量自身對齊參數是4,是因為linux(32)/GCC下如果該類型變量的長度沒有超過CPU的字長,則以該類型變量的長度作為自身對齊參數,如果該類型變量的長度超過CPU字長,則自身對齊參數為CPU字長,而32位系統其CPU字長是4,所以linux(32)/GCC下double類型的變量自身對齊參數是4,如果是在Linux(64)下,則double類型的自身對齊參數是8。

  除了變量的自身對齊參數外,還有一個對齊參數,就是每個編譯器默認的對齊參數#PRagma pack(n),這個值可以通過代碼去設定,如果沒有設定,則取系統的默認值。在windows(32)/VC6.0下,n的取值可以為1、2、4、8,默認情況下為8。在linux(32)/GCC下,n的取值只能為1、2、4,默認情況下為4。注意像DEV-CPP、MinGW等在windows下n的取值和VC的相同。

  了解了這2個概念之后,可以理解上面2條原則了。對于第一條原則,每個變量相對于結構體的首地址的偏移量必須是對齊參數的整數倍,這句話中的對齊參數是取每個變量自身對齊參數和系統默認對齊參數#pragma pack(n)中較小的一個。舉個簡單的例子,比如在結構體A中有變量int a,a的自身對齊參數為4(環境為windows/vc),而VC默認的對齊參數為8,取較小者,則對于a,它相對于結構體A的起始地址的偏移量必須是4的倍數。

  對于第二條原則,結構體變量所占空間的大小是對齊參數的整數倍。這句話中的對齊參數有點復雜,它是取結構體中所有變量的對齊參數的最大值和系統默認對齊參數#pragma pack(n)比較,較小者作為對齊參數。舉個例子假如在結構體A中先后定義了兩個變量int a;double b;對于變量a,它的自身對齊參數為4,而#pragma pack(n)值默認為8,則a的對齊參數為4;b的自身對齊參數為8,而#pragma pack(n)的默認值為8,則b的對齊參數為8。由于a的最終對齊參數為4,b的最終對齊參數為8,那么兩者較大者是8,然后再拿8和#pragma pack(n)作比較,取較小者作為對齊參數,也就是8,即意味著結構體最終的大小必須能被8整除。

下面是測試例子:

注意:以下例子的測試結果均在windows(32)/VC下測試的,其默認對齊參數為8

/*測試sizeof運算符 2011.10.1*/#include <iostream>using namespace std;//#pragma pack(4) //設置4字節對齊 //#pragma pack() //取消4字節對齊 typedef struct node1{ int a; char b; short c;}S1;typedef struct node2{ char a; int b; short c;}S2;typedef struct node3{ int a; short b; static int c;}S3;typedef struct node4{ bool a; S1 s1; short b;}S4;typedef struct node5{ bool a; S1 s1; double b; int c;}S5;int main(int argc, char *argv[]){ cout<<sizeof(char)<<" "<<sizeof(short)<<" "<<sizeof(int)<<" "<<sizeof(float)<<" "<<sizeof(double)<<endl; S1 s1; S2 s2; S3 s3; S4 s4; S5 s5; cout<<sizeof(s1)<<" "<<sizeof(s2)<<" "<<sizeof(s3)<<" "<<sizeof(s4)<<" "<<sizeof(s5)<<endl; return 0;}

下面解釋一下其中的幾個結構體字節分配的情況

比如對于node2

typedef struct node2{ char a; int b; short c;}S2;

sizeof(S2)=12;   對于變量a,它的自身對齊參數為1,#pragma pack(n)默認值為8,則最終a的對齊參數為1,為其分配1字節的空間,它相對于結構體起始地址的偏移量為0,能被4整除;

  對于變量b,它的自身對齊參數為4,#pragma pack(n)默認值為8,則最終b的對齊參數為4,接下來的地址相對于結構體的起始地址的偏移量為1,1不能夠整除4,所以需要在a后面填充3字節使得偏移量達到4,然后再為b分配4字節的空間;

  對于變量c,它的自身對齊參數為2,#pragma pack(n)默認值為8,則最終c的對齊參數為2,而接下來的地址相對于結構體的起始地址的偏移量為8,能整除2,所以直接為c分配2字節的空間。

  此時結構體所占的字節數為1+3+4+2=10字節

  最后由于a,b,c的最終對齊參數分別為1,4,2,最大為4,#pragma pack(n)的默認值為8,則結構體變量最后的大小必須能被4整除。而10不能夠整除4,所以需要在后面填充2字節達到12字節。其存儲如下:

|char|----|----|----| 4字節|--------int--------| 4字節|--short--|----|----| 4字節

  總共占12個字節

對于node3,含有靜態數據成員

typedef struct node3{ int a; short b; static int c;}S3;

  則sizeof(S3)=8.這里結構體中包含靜態數據成員,而靜態數據成員的存放位置與結構體實例的存儲地址無關(注意只有在C++中結構體中才能含有靜態數據成員,而C中結構體中是不允許含有靜態數據成員的)。其在內存中存儲方式如下:

  |--------int--------| 4字節  |--short-|----|----| 4字節

  而變量c是單獨存放在靜態數據區的,因此用siezof計算其大小時沒有將c所占的空間計算進來。

而對于node5,里面含有結構體變量

typedef struct node5{ bool a; S1 s1; double b; int c;}S5;

sizeof(S5)=32。

  對于變量a,其自身對齊參數為1,#pragma pack(n)為8,則a的最終對齊參數為1,為它分配1字節的空間,它相對于結構體起始地址的偏移量為0,能被1整除;

  對于s1,它的自身對齊參數為4(對于結構體變量,它的自身對齊參數為它里面各個變量最終對齊參數的最大值),#pragma pack(n)為8,所以s1的最終對齊參數為4,接下來的地址相對于結構體起始地址的偏移量為1,不能被4整除,所以需要在a后面填充3字節達到4,為其分配8字節的空間;

  對于變量b,它的自身對齊參數為8,#pragma pack(n)的默認值為8,則b的最終對齊參數為8,接下來的地址相對于結構體起始地址的偏移量為12,不能被8整除,所以需要在s1后面填充4字節達到16,再為b分配8字節的空間;

  對于變量c,它的自身對齊參數為4,#pragma pack(n)的默認值為8,則c的最終對齊參數為4,接下來相對于結構體其實地址的偏移量為24,能夠被4整除,所以直接為c分配4字節的空間。

  此時結構體所占字節數為1+3+8+4+8+4=28字節。

  對于整個結構體來說,各個變量的最終對齊參數為1,4,8,4,最大值為8,#pragma pack(n)默認值為8,所以最終結構體的大小必須是8的倍數,因此需要在最后面填充4字節達到32字節。其存儲如下:

  |--------bool--------| 4字節   |---------s1---------| 8字節   |--------------------| 4字節   |--------double------| 8字節   |----int----|---------| 8字節

  另外可以顯示地在程序中使用#pragma pack(n)來設置系統默認的對齊參數,在顯示設置之后,則以設置的值作為標準,其它的和上面所講的類似,就不再贅述了,讀者可以自行上機試驗一下。如果需要取消設置,可以用#pragma pack()來取消。


上一篇:SQL面試題-查詢課程

下一篇:UVA201正方形

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲女同精品视频| 亚洲成人精品久久| 日韩免费视频在线观看| 国产精品丝袜白浆摸在线| 一区二区三区四区在线观看视频| 日韩精品高清在线观看| 日韩免费在线播放| 国产精品免费久久久久久| 国产精品第七影院| 国产精品美女主播在线观看纯欲| 在线视频亚洲欧美| 欧美日韩在线免费| 国内精品免费午夜毛片| 亚洲人线精品午夜| 97超视频免费观看| 97视频在线观看播放| 亚洲成人在线视频播放| www.亚洲一二| 日韩av手机在线观看| 午夜精品美女自拍福到在线| 精品美女永久免费视频| 国产日韩精品入口| 成人伊人精品色xxxx视频| 国产精品91久久久| 91美女片黄在线观看游戏| 久久久日本电影| 国产丝袜一区视频在线观看| 国产精品自拍视频| 国产精品香蕉在线观看| 久久久久国色av免费观看性色| 日韩中文字幕亚洲| 欧美激情按摩在线| 黑人极品videos精品欧美裸| 欧美成人性生活| www高清在线视频日韩欧美| 亚洲欧美国产制服动漫| 日韩成人在线视频观看| 日韩中文字幕在线视频播放| 中文字幕成人在线| 成人精品视频在线| 国产精品久久久久久久app| 久久全国免费视频| 精品国产福利在线| 亚洲va码欧洲m码| 亚洲少妇激情视频| 成人欧美一区二区三区在线湿哒哒| 欧美与黑人午夜性猛交久久久| 精品国产一区二区三区四区在线观看| 午夜精品福利视频| 亚洲深夜福利网站| 91经典在线视频| 4388成人网| 久久久www成人免费精品张筱雨| 日本午夜人人精品| 中文字幕日韩精品在线观看| 精品福利樱桃av导航| 久久久国产一区| 日本成人黄色片| 久久久午夜视频| 亚洲成人激情视频| 亚洲另类激情图| 九九视频直播综合网| 久久成人免费视频| 日韩在线观看免费av| 亚洲精品免费在线视频| 欧美高清自拍一区| 国产精品av免费在线观看| 国产成人精品电影久久久| 青青精品视频播放| 最新国产精品拍自在线播放| 亚洲天堂av网| 欧美大胆a视频| 国产亚洲视频在线观看| 国产mv久久久| 国产亚洲福利一区| 成人写真视频福利网| 国产精品第一页在线| 亚洲成人av在线| 一区二区三区视频观看| 国产精品99久久久久久久久| 亚洲精品自产拍| 欧美在线免费看| 亚洲自拍另类欧美丝袜| 福利精品视频在线| 在线精品国产成人综合| 亚洲乱码一区av黑人高潮| 久久精品视频一| 欧美性极品少妇精品网站| 国产欧美日韩丝袜精品一区| 中国日韩欧美久久久久久久久| 中文字幕欧美日韩在线| 色伦专区97中文字幕| 久久精品色欧美aⅴ一区二区| 日韩中文在线中文网在线观看| 日韩精品亚洲精品| 97精品久久久中文字幕免费| 国产成人一区二区三区电影| 亚洲第一福利在线观看| 久久久精品国产| 成人写真视频福利网| 欧美肥臀大乳一区二区免费视频| 国产成人精品视| 麻豆成人在线看| 久久亚洲成人精品| 日韩精品视频三区| 性欧美xxxx| 国产精品999999| 欧美午夜丰满在线18影院| 亚洲一区二区三区777| 亚洲一区二区三区毛片| 欧美极品少妇xxxxⅹ裸体艺术| 亚洲缚视频在线观看| 欧美成人激情视频免费观看| 在线成人一区二区| 国内精品视频在线| 欧美日韩国内自拍| 欧美极品少妇xxxxx| 国产精品一二三视频| 欧美性猛交xxxxx水多| 色婷婷久久av| 欧美美最猛性xxxxxx| 久久精品国产亚洲7777| 亚洲天堂一区二区三区| 亚洲国产欧美一区二区三区同亚洲| 欧美精品在线看| 91精品国产91久久久久久吃药| 91在线视频精品| 成人免费在线视频网址| 欧美大胆在线视频| 福利精品视频在线| 成人免费观看49www在线观看| 亚洲国产又黄又爽女人高潮的| 亚洲国产成人精品一区二区| 91九色国产社区在线观看| 国产视频精品一区二区三区| 国产精品69精品一区二区三区| 亚洲国产又黄又爽女人高潮的| 国产精品一区二区久久国产| 日韩hd视频在线观看| 国精产品一区一区三区有限在线| 国产精品pans私拍| 亚洲国产精品999| 日韩av一区二区在线| 国产精品国产三级国产aⅴ9色| 日韩av在线不卡| 午夜伦理精品一区| 亚洲性av网站| 国产欧美日韩视频| 日韩中文理论片| 国产视频丨精品|在线观看| 精品欧美国产一区二区三区| 欧美另类69精品久久久久9999| 国产精品亚洲视频在线观看| 成人性生交大片免费看视频直播| 91精品国产乱码久久久久久久久| 国产91色在线免费| 日韩精品视频观看| 狠狠躁夜夜躁人人爽天天天天97| 国产99久久精品一区二区 夜夜躁日日躁| 92福利视频午夜1000合集在线观看| 4438全国亚洲精品在线观看视频| 欧美成人免费小视频| 一区二区三区国产视频| 日韩av在线网址|