联合体union的使用

来源:互联网 发布:中国数据南京 编辑:程序博客网 时间:2024/05/18 01:33

1.联合体union的基本特性——和struct的同与不同

union,中文名“联合体、共用体”,在某种程度上类似结构体struct的一种数据结构,共用体(union)和结构体(struct)同样可以包含很多种数据类型和变量。

不过区别也挺明显:

结构体(struct)中所有变量是“共存”的——优点是“有容乃大”,全面;缺点是struct内存空间的分配是粗放的,不管用不用,全分配。

而联合体(union)中是各变量是“互斥”的——缺点就是不够“包容”;但优点是内存使用更为精细灵活,也节省了内存空间。


2.双刃剑——多种访问内存途径共存

一个例子了然:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. //example  
  2. #include<stdio.h>  
  3. union var{  
  4.         long int l;  
  5.         int i;  
  6. };  
  7. main(){  
  8.         union var v;  
  9.         v.l = 5;  
  10.         printf("v.l is %d\n",v.i);  
  11.         v.i = 6;  
  12.         printf("now v.l is %ld! the address is %p\n",v.l,&v.l);  
  13.         printf("now v.i is %d! the address is %p\n",v.i,&v.i);  
  14. }  
  15. 结果:  
  16. v.l is 5  
  17. now v.l is 6! the address is 0xbfad1e2c  
  18. now v.i is 6! the address is 0xbfad1e2c  

所以说,管union的叫共用体还真是贴切——完全就是共用一个内存首地址,并且各种变量名都可以同时使用,操作也是共同生效。如此多的access内存手段,确实好用,不过这些“手段”之间却没法互相屏蔽——就好像数组+下标和指针+偏移一样。

上例中我改了v.i的值,结果v.l也能读取,那么也许我还以为v.l是我想要的值呢,因为上边提到了union的内存首地址肯定是相同的,那么还有一种情况和上边类似:

一个int数组变量a,一个long int(32位机中,long int占4字节,与int相同)变量b,我即使没给int变量b赋值,因为数据类型相同,我使用int变量b也完全会拿出int数组a中的a[0]来,一些时候一不小心用上,还以为用的就是变量b呢~

这种逻辑上的错误是很难找出来的(只有当数据类型相去甚远的时候稍好,出个乱码什么的很容易发现错误)。


PS:感谢热心网友的提醒“在union定义结束时加分号”,其实是可以不加的,因为他不在主函数内,不是执行的语句,如果是主函数内声明的union就必须加分号了,在主函数内不加分号就涉及到基础常识了——没有分号隔开怎能叫一句。


3.联合体union和大小端(big-endian、little-endian):

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include<stdio.h>  
  2. union var{  
  3.         char c[4];  
  4.         int i;  
  5. };  
  6.   
  7. int main(){  
  8.         union var data;  
  9.         data.c[0] = 0x04;//因为是char类型,数字不要太大,算算ascii的范围~  
  10.         data.c[1] = 0x03;//写成16进制为了方便直接打印内存中的值对比  
  11.         data.c[2] = 0x02;  
  12.         data.c[3] = 0x11;  
  13. //数组中下标低的,地址也低,按地址从低到高,内存内容依次为:04,03,02,11。总共四字节!  
  14. //而把四个字节作为一个整体(不分类型,直接打印十六进制),应该从内存高地址到低地址看,0x11020304,低位04放在低地址上。  
  15.         printf("%x\n",data.i);  
  16. }  

结果:
11020304
证明我的32位linux是小端(little-endian)
0 0
原创粉丝点击