天天看點

c語言中結構體的大小和記憶體對齊問題

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) 結構體的總大小為結構體最寬基本類型成員大小的整數倍,如有需要編譯器會在最末一個成員之後加上填充位元組。例如上面第 三 結構體變量。