首先,結構在C語言中也是一種數據類型,叫作聚組類型(還包括數組)。他和其餘的數據類型是同樣的,在定義一個結構體的時候,系統並不會爲他真正的分配內存空間(定義的結構體變量要在編譯的階段才分配空間,而結構體指針要顯示的使用malloca來分配空間),也就是說,在定義結構體這種數據類型的時候是不會分配內存空間的,只有在定義變量的時候,纔會分配。web
下面是摘自百度百科 對結構題存儲的三點:數組
1) 結構體變量的首地址可以被其最寬基本類型成員的大小所整除; 數據結構
2) 結構體每一個成員相對於結構體首地址的偏移量都是成員大小的整數倍,若有須要編譯器會 在成員之間加上填充字節;ide
3) 結構體的總大小爲結構體最寬基本類型成員大小的整數倍,若有須要編譯器會在最末一個成員以後加上填充字節spa
下面是來自《c和指針》的介紹指針
struct s1{code
char a;orm
int b;blog
char c;內存
};
首先,結構體在存儲的時候,結構體的首地址必須可以被其中最寬數據類型整除。(在s1中,最寬數據類型爲int,在32位系統中爲4Byte),
其次,參照第二條,第一個數據時char(已經保證了,結構的起始地址是4的整數倍),存儲一個char,佔一個Byte,要保證下一個int的存儲起始地址是4的整數倍,因此要在char後面填充三個Byte,而後在存儲第三個數據。
第三,最後一個也是char類型,他就佔一個Byte,確定是他存儲位置的整數倍,最後參照第三條,結構體的總大小爲最寬數據類型的整數倍,因此會在第二個char以後再填充三個Byte。
這樣的話,總共佔據的空間是1+3+4+1+3 = 12(紅色爲填充字符)
【可是】,調換一下結構中數據成員的順序
struct s1{
int b;
char a;
char c;
};
一樣地分析4+1+1+2 = 8
相比之下,存儲空間的效率提升33%。
如下是系統對結構體的內存分配的詳細介紹:
一、結構體變量的首地址是結構體中最寬數據類型的整數倍。
編譯器在給結構體開闢空間時,首先找到結構體中最寬的基本數據類型,而後尋找內存地址能是該基本數據類型的整倍的位置,做爲結構體的首地址。
2、結構體每一個成員相對於結構體首地址的偏移量(offset)都是成員大小的整數倍,若有須要編譯器會在成員之間加上填充字節。
爲結構體的一個成員開闢空間以前,編譯器首先檢查預開闢空間的首地址相對於結構體首地址的偏移是否是本成員的整數倍,如果,則存放本成員,反之,則在本成員和上一個成員之間填充必定的字節,以達到整數倍的要求,也就是將預開闢空間的首地址後移幾個字節。
三、結構體的總大小爲結構體中最寬基本數據成員的整數倍。若有須要,編譯器將會在結構體的添加填充字符。
四、結構體中的數據成員按照所佔空間從大到小的順序來排列的話,這樣存儲空間就會得以提升。
四、如今對四條進行修正。在組織數據結構的數據成員的時候,能夠將相同類型的成員放在一塊兒,這樣就減小了編譯器爲了對齊而添加的填充字符。
【提示】:
有些時候,咱們不該該對結構的數據成員進行重排以減小因對齊帶來的空間損失。由於在咱們對數據成員重拍的時候,每每破壞了數據間的關聯性,從而下降了程序的可讀性和可維護性。
綜上,咱們能夠得出,在對結構的成員進行重排的時候,即要考慮存儲空間的使用效率,又要考慮程序的可讀性與可維護性。
下面的代碼是對上述幾條的驗證:
1 #include<stdio.h> 2 #include<stddef.h> 3 struct s1{ 4 int a; 5 char b; 6 char c; 7 }; 8 9 struct s2 { 10 char b; 11 char c; 12 int a; 13 14 }; 15 int main(){ 16 /* 17 struct s1 s; 18 s.a = 12; 19 s.b = 'a'; 20 s.c = 'b'; 21 22 printf("int s.a size: %d \n",offsetof(struct s1,a)); 23 printf("char s.b size: %d \n",offsetof(struct s1,b)); 24 printf("char s.b size: %d \n",offsetof(struct s1,c)); 25 printf("size of struct s1: %d\n",sizeof(struct s1)); 26 */ 27 28 29 struct s2 s; 30 s.a = 12; 31 s.b = 'a'; 32 s.c = 'b'; 33 34 printf("int s.a size: %d \n",offsetof(struct s2,a)); 35 printf("char s.b size: %d \n",offsetof(struct s2,b)); 36 printf("char s.b size: %d \n",offsetof(struct s2,c)); 37 printf("size of struct s1: %d\n",sizeof(struct s2)); 38 }