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;