如何使用联合

声明联合变量后,有很多方法设置它的值。

C89方式

如果联合要保存第一个字段的值,就可以用C89表示法,只要用花括号把值括起来,就可以把值赋给联合中第一个字段。

如何使用联合 - 图1

指定初始化器

指定初始化器(designated initializer)按名设置联合字段的值:

如何使用联合 - 图2

“点”表示法

第三种设置联合值的方法是在第一行创建变量,然后在第二行设置字段的值。

  1. quantity q;
  2. q.volume = 3.7;

切记,无论用哪种方法设置联合的值,都只会保存一条数据。联合只是提供了一种让你创建支持不同数据类型的变量的方法。

这里没有蠢问题

问:为什么联合的大小取决于最长的字段?

:计算机需要保证联合的大小固定。唯一的办法就是让它足够大,任何一个字段都能装得下。

问:为什么C89表示法只能设置第一个字段?如果我传给联合float值,为什么不把它设为第一个float字段?

:这么做是为了避免歧义。假设你有一个float字段和一个double字段,那么计算机应该把{2.1}保存成float还是double呢?每次都把值保存在第一个字段中,你就知道数据是怎么初始化的。

 

如何使用联合 - 图3C标准礼貌指南

可以用“指定初始化器”按名设置结构和联合字段,它属于C99标准。绝大多数现代编译器都支持“指定初始化器”,但如果你用的是C语言的变种,就要小心了,比如ObjectiveC支持“指定初始化器”,但C++不支持。

如何使用联合 - 图4

是的,“指定初始化器”也可以用来设置结构字段的初值。

如果结构有很多字段,但你只想为其中某些字段设初值,“指定初始化器”就非常有用。同时它还能够提高代码的可读性:

如何使用联合 - 图5

联合常和结构一起用

创建联合相当于创建新的数据类型,也就是说可以在任何地方使用它的值,就像使用整型或结构那样的数据类型。例如,可以把联合和结构结合起来:

  1. typedef struct {
  2. const char *name;
  3. const char *country;
  4. quantity amount;
  5. } fruit_order;

可以用之前使用过的“点”表示法或“->”表示法访问“结构/联合”组合中的值:

如何使用联合 - 图6

如何使用联合 - 图7晕头转向的调酒师

Head First酒吧的“玛格丽特之夜”,一群人喝得酩酊大醉以后把配方弄乱了,你能否为每种玛格丽特酒找到相应的代码?

基本原料如下:

  1. typedef union {
  2. float lemon;
  3. int lime_pieces;
  4. } lemon_lime;
  5.  
  6. typedef struct {
  7. float tequila;
  8. float cointreau;
  9. lemon_lime citrus;
  10. } margarita;

下面是几种不同的玛格丽特酒:

如何使用联合 - 图8

最后,这里有一些不同的调法和他们制作的配方。为了生成正确的配方,应该把哪些玛格丽特酒加入代码?

如何使用联合 - 图9

如何使用联合 - 图10变身编译器

有的代码能编译,有的不能。你的任务是扮演编译器,说出哪段代码能编译,如果不能请说明理由。

如何使用联合 - 图11

如何使用联合 - 图12晕头转向的调酒师解答

Head First酒吧的“玛格丽特之夜”,一群人喝得酩酊大醉以后把配方弄乱了,你将为每种玛格丽特酒找到相应的代码。

基本原料如下:

  1. typedef union {
  2. float lemon;
  3. int lime_pieces;
  4. } lemon_lime;
  5.  
  6. typedef struct {
  7. float tequila;
  8. float cointreau;
  9. lemon_lime citrus;
  10. } margarita;

下面是几种不同的玛格丽特酒:

如何使用联合 - 图13

最后,这里有一些不同的调法和他们制作的配方。为了生成正确的配方,应该把哪些玛格丽特酒加入代码?

如何使用联合 - 图14

如何使用联合 - 图15变身编译器

有的代码能编译,有的不能。你的任务是扮演编译器,说出哪段代码能编译,如果不能请说明理由。

如何使用联合 - 图16

 

如何使用联合 - 图17

好问题:可以在联合中保存各种可能的值,但保存以后,就无法知道它的类型。

编译器不会记录你在联合中设置或读取过哪些字段。我们完全可以设置一个字段,读取另一个字段,但有时这会造成很严重的后果。

如何使用联合 - 图18

你需要某种方法记录我们在联合中保存了什么值。C程序员常用的一种技巧是创建枚举。