編譯器會爲結構體變量中的每一個數據成員分配不一樣的地址空間,也就是說,結構體變量中的數據程序是並列關係,而編譯器爲共用體變量中的數據成員分配的是同一塊內存,每一個時刻只有一個數據成員有意義,從地址的角度來看二者的差別,形象地代表了這一點數組
#include <stdio.h> #include <stdlib.h> #include <string.h> //初始化方式和結構體相似 union data{ //相似於結構體變量,共享內存,共用體的大小等於最長的那一段,共用體變量在任什麼時候刻只有一個成員變量存在,定義的時候不能初始化,只有在建立的時候才能初始化 int price; char brand[20]; }d1, d2, *pData, data[10]; union key{ //共用體會存在字節數填充,直到能夠被最小類型字節數整除,double有8個字節,a數組有9個,再填充7個字節,剛好被double整除 //內存對齊的方式,分別CPU尋址 double d; char a[9]; } k; //sizeof(k) =16 void main(){ printf("%d\n", sizeof(d1)); //20 d1.price = 100; strcpy(d1.brand,"IBM"); d2 =d1; //共用體變量能夠直接賦值 printf("%d,%s\n",d1.price,d1.brand); //5063241,IBM 只正確顯示,最後一個賦值的變量,其餘的數據解析爲錯誤數據,由於他們共用一段內存 union data uniondata = {100 }; //大括號初始化時,只能初始化第一個成員變量!!!共用同一片空間 //共用體變量的三種引用方式和結構體變量相似 }
//初始化方式和結構體相似 union data{ //相似於結構體變量,共享內存,共用體的大小等於最長的那一段,共用體變量在任什麼時候刻只有一個成員變量存在,定義的時候不能初始化,只有在建立的時候才能初始化 int price; char brand[20]; }d1, d2, *pData, data[10]; union key{ //共用體會存在字節數填充,直到能夠被最小類型字節數整除,double有8個字節,a數組有9個,再填充7個字節,剛好被double整除 //內存對齊的方式,分別CPU尋址 double d; char a[9]; } k; //sizeof(k) =16 void main(){ printf("%d\n", sizeof(d1)); //20 d1.price = 100; strcpy(d1.brand,"IBM"); d2 =d1; //共用體變量能夠直接賦值 printf("%d,%s\n",d1.price,d1.brand); //5063241,IBM 只正確顯示,最後一個賦值的變量,其餘的數據解析爲錯誤數據,由於他們共用一段內存 union data uniondata = {100 }; //大括號初始化時,只能初始化第一個成員變量!!!共用同一片空間 //共用體變量的三種引用方式和結構體變量相似
結構體變量佔據的內存單元的個數應當大於等於其內部全部數據成員佔據內存單元數的和spa
出於效率的考慮,C語言引入了字節對齊機制,通常來講,不一樣的編譯器字節對齊機制有所不一樣,但仍是有如下3條通用準則:
(1)結構體變量的大小可以被其最寬基本類型成員的大小所整除;
(2)結構體每一個成員相對於結構體首地址的偏移量(offset)都是成員大小的整數倍,若有須要編譯器會在成員之間加上填充字節(internal adding);
(3)結構體的總大小爲結構體最寬基本類型成員大小的整數倍,若有須要編譯器會在最末一個成員以後加上填充字節(trailing padding)。
字節對齊第3條準則說起最寬基本類型的概念,所謂基本類型是指像char、short、int、float、double這樣的內置數據類型。「數據寬度」就是指其sizeof的大小。諸如結構體、共用體和數組等都不是基本數據類型code
#include <stdio.h> #include <stdlib.h> #include <string.h> //第一步:找出最寬的基本數據類型 //第二步:每一個成員變量均可以被最寬基本類型整除 //第三步:累加 struct data1{ char c; // 4 char必須能被最寬基本類型整除,因此也是4個字節 int price; // 4 int是最寬基本數據類型 4個字節 char brand[19];// 20 數組是否是基本數據類型,基本數據是char類型,也要能被4整除 因此填充1個字節,就是20 }d1; //sizeof(d1)=28 struct data2{ char c; // 1 char必須能被最寬基本類型整除,因此也是1個字節 char price; // 1 char 是最寬基本數據類型 1個字節 char brand[19];// 19 數組是否是基本數據類型,基本數據是char類型,也要能被1整除 無需填充 }d2; //sizeof(d2)=21 struct data3{ char c; // 8 char必須能被最寬基本類型8整除,因此也是8個字節 double price; // 8 char 是最寬基本數據類型8個字節 char brand[19];// 24 數組是否是基本數據類型,基本數據是char類型,也要能被8整除, 填充5個字節,24個字節 }d3; //sizeof(d3)=40 void main(){ printf("%d\n", sizeof(d3)); printf("%x\n",&d1); printf("%x\n",&d1.c); printf("%x\n",&d1.price); printf("%x\n",&d1.brand); /* * 406400 &d1 * 406400 &d1.c +4 406404 &d1.price + 4 406408 &d1.brand +20 */ }