看結構體和共用體部分的時候,遇到了一個新名詞“內存對齊”。先引入問題。如下:
1 struct student
2 {
3 char name[20];
4 int age;
5 char sex;
6 char phone[15];
7 };
8 struct student p1;
sizeof(p1)=?
這個很簡單得出答案,即20+4+1+15=40Byte。如果將phone[15]改為phone[16],結果是44。難道不是41嗎?
這裡便要引入內存對齊的概念。內存為了提高訪問效率,規定以結構體中最大的基本單位長度為對齊標准。即實際分配的內存大小是對齊標准的整數倍(必要條件)。在上面的結構體中,最大的基本類型是int。因此以4Byte為對其標准。所以實際內存大小應該為4的整數倍,即為44Byte。
也許你有疑惑:name[20]不是要20Byte嗎,為什麼以4Byte為對齊標准?請注意這裡的基本類型。name[20]是一個字符串數組,數組屬於復合的數據類型。復合的數據類型還有結構體,共用體。基本的數據類型是整型,字符型,浮點型。如果你還有不解,那麼看下題:
1 struct score
2 {
3 float english;
4 float math;
5 float computer;
6 };
7
8 struct student
9 {
10 char name[10];
11 int age;
12 char sex;
13 struct score st_score;
14 };
在student結構體中含有數據類型為struct score這樣的變量。struct score的大小為12Byte,也是struct student結構體中最大的數據類型,但是我們的對齊標准是4Byte,就如我們剛說的那樣,內存的對齊標准是取結構體中最大的基本數據類型,這裡我們取sizeof(int)。
再看下面的問題:
1 union data1
2 {
3 int i;
4 char c;
5 char str[9];
6 };
7
8 struct data2
9 {
10 int i;
11 char c;
12 char str[9];
13 };
sizeof(struct data1)=?
sizeof(struct data2)=?
對於前者,由於共用體的存儲大小由最大的成員來決定,因此上題中共用體的存儲大小為9Byte,考慮到內存對齊,它以sizeof(int)=4Byte來對齊,因此實際內存分配大小是12Byte。對於後者,存儲大小是4+1+9=14Byte,這個結構體以4對齊,因此實際分配大小為16Byte。
現在你應該對於共用體和結構體的內存對齊有所了解了。那麼再接著往下看:
1 struct data
2 {
3 char c;
4 double d;
5 char ch;
6 }
sizeof(struct data)=?
有了上面的理解,10肯定不會是答案,那麼會是16吧。也錯。正確答案是24。你可能會感到莫名其妙:按照上面所說的方法,以8為對齊標准,那麼10不是8的倍數,那就是16呀。為什麼呢?請你耐心看下面。
首先我們知道結構體變量是分配的連續內存空間。d毫無疑問是分配8Byte,對於d“前面”的c,按照對齊標准我們應該分配8Byte,而d後面的ch,按照對齊標准也應該分配8Byte。因此結果是24。
如果這樣:
1 struct data
2 {
3 double d;
4 char c;
5 char ch;
6 }
sizeof(struct data)=16。
因為內存沒必要分別為c和ch分配8Byte來進行對齊,將它們放在一個8byte裡就可以實現內存對齊。上面在引入內存對齊概念的時候,用括號特別注釋必要條件便是說明此處內容。
摘自 GNU/Free