union myun { struct { int x; int y; int z; }u; int k; }a; int main() { a.u.x =4; a.u.y =5; a.u.z =6; a.k = 0; printf("%d %d %d\n",a.u.x,a.u.y,a.u.z); return 0; }
union類型是共享內存的,以size最大的結構做爲本身的大小,這樣的話,myun這個結構就包含u這個結構體,而大小也等於u這個結構體 的大小,在內存中的排列爲聲明的順序x,y,z從低到高,而後賦值的時候,在內存中,就是x的位置放置4,y的位置放置5,z的位置放置6,如今對k賦 值,對k的賦值由於是union,要共享內存,因此從union的首地址開始放置,首地址開始的位置實際上是x的位置,這樣原來內存中x的位置就被k所賦的 值代替了,就變爲0了,這個時候要進行打印,就直接看內存裏就好了,x的位置也就是k的位置是0,而y,z的位置的值沒有改變,因此應該是0,5,6網絡
union myun { struct { int x; int y; int z; }u; int k; int j; }a; int main() { a.u.x =4; a.u.y =5; a.u.z =6; a.k = 0; a.j = 1; printf("%d %d %d\n",a.u.x,a.u.y,a.u.z); return 0; }
結果爲1,5,6 由於仍是從最低的地址開始覆蓋,而不是像有些人想象的是 0,1,6數據結構
typedef unsigned char BYTE; int main(int argc, char* argv[]) { unsigned int num,*p; p = # num = 0; *(BYTE *)p = 0xff; if(num == 0xff) { printf("The endian of cpu is little\n"); } else //num == 0xff000000
{ printf("The endian of cpu is big\n"); } return 0; }
除了上述方法(經過指針類型強制轉換並對整型數據首字節賦值,判斷該賦值賦給了高位仍是低位)外,還有沒有更好的辦法呢?spa
咱們知道,union 的成員自己就被存放在相同的內存空間(共享內存,正是union 發揮做用、作貢獻的去處),所以,咱們能夠將一個CHAR/BYTE 數據和一個整型數據同時做爲一個union 的成員,得出以下答案:操作系統
int checkCPU() { {
union w { int a; char b; } c; c.a = 1; return (c.b == 1); } }
返回1表示是:Little endian,0表示:Big endian指針
static union { char c[4]; unsigned long mylong; } endian_test = {{ 'l', '?', '?', 'b' } }; #define ENDIANNESS ((char)endian_test.mylong)
Linux 的內核做者們僅僅用一個union 變量和一個簡單的宏定義就實現了一大段代碼一樣的功能!由以上一段代碼咱們能夠深入領會到Linux 源代碼的精妙之處!(若是ENDIANNESS=’l’表示系統爲little endian, 爲’b’表示big endian )code
試題二:假設網絡節點A 和網絡節點B 中的通訊協議涉及四類報文,報文格式爲「報文類型字段+報文內容的結構體」,四個報文內容的結構體類型分別爲STRUCTTYPE1~ STRUCTTYPE4,請編寫程序以最簡單的方式組
typedef unsigned char BYTE; //報文內容聯合體 typedef union tagPacketContent { STRUCTTYPE1 pkt1; STRUCTTYPE2 pkt2; STRUCTTYPE3 pkt1; STRUCTTYPE4 pkt2; }PacketContent; //統一的報文數據結構 typedef struct tagPacket { BYTE pktType; PacketContent pktContent; }Packet;