C union(联合体)作用——玩转 union

C语言中,union相对于struct使用的次数在大部分项目中都处于明显的劣势,这和union的存储方式的特性有很大的关系。在union中,所有的字段都有相同的偏移量,而且所有的字段都是相互重叠的,union的大小是其中最大字段的大小。那我们就知道,如果所有的字段是相互重叠的,那改变其中任何一个字段的值,其他字段的值都会受到影响,也会发生变化。这就造成union在实际使用中使用的频率不会那么高,甚至会认为可能也没有什么用。如果想要使用的话,那么union中的各个字段的使用必须是互斥的,任意时刻只能使用一个。在阅读《编程卓越之道》有看到union的一些作用,感觉确实可以一用,有一种豁然开朗的感觉。我整理一下《编程卓越之道》的内容和我自己的理解。

1 判断大小端,union大显身手
我记得union的第一个作用就是判断机器的大小端了,当时毕业找工作,很多公司都喜欢出这道题。一个整数在大小端机器上面存储的顺序是不一样,而union中的各个字段的偏移地址是相同的,那一个数在在大小端机器中存储到union中,如果将这个数拆分,各个部分也会不同。直接看例子吧,代码胜于雄辩。

typedef union {
unsigned long bits32;
unsigned char bytes[4];
} TheValue;
TheValue theValue;
int isLittleEndian = 0; 
theValue.bytes[0] = 0;
theValue.bytes[1] = 1;
theValue.bytes[2] = 0;
theValue.bytes[3] = 0;
isLittleEndian = (theValue.bits32 == 256);

2 创建别名
就是这个感觉非常有用,因为程序中经常会进行类型的强制转换,如果不小心可能就会出错,那么我们就可以利用union中的字段代表想要得到的类型,尤其是指针类型,尤其是代码整合过程中,如果使用了第三方的库,需要将第三方的库merge到自己的代码中,由于编码习惯,命名规则的不同,还是需要将其他库的一些类型转换为自己习惯的方式或者公司的方式。一般情况我们是能看到库的header file的,结构类型什么的都可以看到。我们会按照库的header file写一份自己的。
例如库中header file有一个struct 名字是ThirdTest
那么我们header file有一个对应的struct 名字是OurTestThird
那么就可以弄一个union

typedef union {
    ThirdTest * thirdTest;
    OurTestThird *ourTestThird;
} TestThird;

那我们使用一下

TestThird testThird;
testThird.thirdTest = getCallOneFunction(); //这个一个库函数,返回的类型是ThirdTest *
CallOurSomeOneFunction(testThird. ourTestThird); //这个是自己的函数,参数类型是OurTestThird *

那这个union TestThird就起到了将类型ThirdTest *强转为OurTestThird *的作用,union起到了一个桥梁的作用和粘合剂的作用,不然就需要一个表将自己的类型和库的类型一一对应起来。
当然这个例子有些牵强,有很多办法将类型对应起来,这里只是针对别名列举一个例子而已。

3 将union中较大的对象分解成组成这个对象的各个字节。
直接看例子吧,这个是完全利用union的存储特性实现的。来自于《编程卓越之道》。

typedef union {
unsiged int u;
unsiged char bytes[4];
} asBytes;
asBytes composite;
composite.u = 1234576890;
printf (“HO byte of composite.u is %u, LO byte is %u\n”, composite.bytes[3], composite.bytes[0]);

4 其他
Union和struct结合使用是最常见的使用方法。
举一个例子不知道是否恰当。例如一个系统分为上中下三层,上层和下层是对应的,而中间层是一个转换层(传输层),也就是说上层可能有A和B两个不同的系统,下层有C和D两个系统,而中层E是唯一的,E能保证A和C,B和D正常运行。假设A需要向C传入一个struct为StructAC类型的数据,B向D传入一个struct为StructBD类型的数据,而E作为中间层要能够保证传输StructAC和StructBD类型的数据,那中间层E就可以定义一个union

typedef union {
StructAC ac;
StructBD bd;
} UnionE;

E接收到上层的数据后,把数据封装成UnionE 类型的data,E向下层传输就直接传输UnionE的data,而下层C和D就可以直接转为StructAC和StructBD处理就好了。(A向E,B向E不是直接传输的StructAC,StructBD类型的数据,可能是一些原始数据,E需要一些逻辑将这些原始数据转为UnionE)

当我们遇到一个新的知识点的时候,可能理解很快,但是了解其真实的意图还是要多看多学,不断的积累,才能不断丰富自己的眼界。


版权声明:本文为diangangqin原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。