Struct結構體是C/C++語言中用來自定義數據類型的,
我們學習結構體知識,除了學習一些相關的基本知識外,我們必須瞭解其在計算機內部具體的存在,主要問題集中在結構的大小以及內存的分配問題
一、字節對齊
現代計算機中內存空間都是按照byte劃分的,從理論上講似乎對任何類型的變量的訪問可以從任何地址開始,但實際情況是在訪問特定類型變量的時候經常在特定的內存地址訪問,這就需要各種類型數據按照一定的規則在空間上排列,而不是順序的一個接一個的排放,這就是對齊。我們拿32位系統來說(以下內容均對於32位系統),按我的理解比如一個char型變量c之後我們接着需要存儲一個int型的變量i假如c變量的首地址是0x0044ff33,那麼變量i雖然一定存儲在0x0044ff33之後,但是其首地址一定不會是0x0044ff34,而會是0x0044ff38,因爲這樣對於計算機的內部處理將更加的方便和快捷。
二、結構體大小及內存分配
我們舉兩個例子來討論:
1、struct Demo
{
char c;
int i;
};
struct Demo demo1;
那麼我們提出問題:sizeof(demo1) = ?
&demo1 = ?
&demo1.c = ?
&demo.i = ?
答案: sizeof(demo1) = 8 字節
&demo1 = 0x0022ff48
&demo1.c = 0x0022ff48
&demo1.i = 0x0022ff4c
根據編譯器的不同,對於地址空間:0x0022ff48—0x0022ff4c做不同處理,有的填充隨機字符(如VC,會在這裏填充CC CC CC),而有的編譯器也有不同處理,比如填0或者空着
2、struct Demo
{
int i;
char c;
int j;
};
struct Demo demo2;
那麼我們提出問題:sizeof(demo2) = ?
&demo2 = ?
&demo2.i = ?
&demo2.c = ?
&demo2.j = ?
答案: sizeof(demo2) = 12 字節
&demo2 = 0x0022ff44
&demo2.i =0x0022ff44
&demo2.c = 0x0022ff48
&demo2.j =0x0022ff4c
根據編譯器的不同,對於地址空間:0x0022ff48—0x0022ff4c做不同處理,有的填充隨機字符(如VC,會在這裏填充CC CC CC),而有的編譯器也有不同處理,比如填0或者空着
3、struct Demo
{
int i;
char c;
};
struct Demo demo3;
那麼我們提出問題:sizeof(demo3) = ?
&demo3 = ?
&demo3.i = ?
&demo3.c = ?
答案: sizeof(demo3) = 12 字節
&demo3 = 0x0022ff44
&demo3.i = 0x0022ff44
&demo3.c = 0x0022ff48
根據編譯器的不同,對於地址空間:0x0022ff49—0022ff4c做不同處理,有的填充隨機字符(如VC,會在這裏填充CC CC CC),而有的編譯器也有不同處理,比如填0或者空着這與上面兩個不同,因爲缺口在後面,但是本質意義是相同的。、
三、規則
其實字節對齊的細節和具體編譯器實現相關,但一般而言,滿足三個準則:
1) 結構體變量的首地址能夠被其最寬基本類型成員的大小所整除;
2) 結構體每個成員相對於結構體首地址的偏移量都是成員大小的整數倍,如有需要編譯器會在成員之間加上填充字節;例如上面第一結構體變量的地址空間。
3) 結構體的總大小爲結構體最寬基本類型成員大小的整數倍,如有需要編譯器會在最末一個成員之後加上填充字節。例如上面第三結構體變量。