联合
- 引言
- 联合的声明
- 联合的声明
- typedef命名联合
- 设置联合的值
- C89(标准)方式
- 使用`.`操作符进行指定初始化
- 联合的内存布局
- 联合的使用场景
- 节省内存资源
- 实际应用案例分析
- 总结
引言
在学习C语言基础时,联合和结构体是两个经常被拿来比较的概念。虽然它们在某些方面相似,比如:它们都能存储多个成员、在声明、初始化、访问等方面都有很多共同点。
所以如果想学习联合,结构体是不得不学习的一部分,请查看我的博客结构体。
联合相对于结构体而言使用了一种特殊的内存使用方法。联合允许在相同的内存位置存储不同的数据类型,当然,这种特性只有在特定场景下非常有用,尤其是在需要节省内存或者处理多种数据类型但不需要同时使用它们的场景中。
联合的声明
联合的声明
联合的声明与结构体类似,声明联合的语法代码如下:
union Myunion{int intValue;float floatValue;char *string;
};
这里的union
为声明联合的关键字,Myunion
是联合的变量类型。
typedef命名联合
这一点也和结构体的命名非常类似。
typedef union{int intValue;float floatValue;char *string;
}Myunion;
这一串的代码与上面的代码的区别是使用了typedef将结构体起了一个新的名字,这样在之后的编码过程中就不需要使用union
来定义联合。
设置联合的值
C89(标准)方式
如果联合想保存第一个字段的值,只要用花括号把值括起来,就可以把值
赋给联合中的第一个字段。
typedef union {short count;float weight;float volume;
}quantity;quantity q={4}//相当于将count赋值为4
使用.
操作符进行指定初始化
.
操作符也是我们的老朋友了,只不过这次我们需要指定将某一个字段初始化。
typedef union {short count;float weight;float volume;
}quantity;quantity q={.weight=1.5}//相当于将weight赋值为1.5
//或者用下面的代码:
quantity q;//先进行声明。
q.volume=3.7;//对volume赋值为3.7。
联合的内存布局
在上述示例中,不管是intValue
、floatValue
还是string
,它们都占据了相同的内存位置。这是联合的关键特点:同一时间只能有效地存储一个成员的值,因为所有成员共享内存。
typedef union {short count;float weight;float volume;
}quantity;
这里的三个变量count
、weight
、volume
在同一时间只能有效地存储一个的值,如果强行进行定义,就会丢失数据。
为了能够表达所有的变量,short
占2个字节、float
占4个字节。以占最大内存的float
为标准,联合占内存大小为4个字节。
在这里,针对内存布局,我们可以使用下面的代码进行说明:
union MyUnion data;
data.intValue = 3;//
printf("%d\n", data.intValue);
data.floatValue = 4.5;
printf("%d\n", data.floatValue);
printf("%d\n", data.intValue);// 如果执行这行代码,此时,尝试访问data.intValue将得到一个未定义的结果,因为最后存储的是floatValue。
联合的使用场景
节省内存资源
在系统中,内存资源是有限的,联合在一定程度上可以有效减少内存的占用。联合通过共享内存,不同类型的数据可以被折叠存储,减少了各个变量对内存的占用。
实际应用案例分析
在实际应用中,联合的使用非常广泛。例如,在网络通信中处理不同类型的消息包,或者在图形用户界面中处理不同类型的事件数据。
我们以一个现实的例子来说明这个问题,比如描述苹果,我们可以从个数、体积、质量等方面进行描述,我们只需要用一个量就可以描述苹果这个事物
union quantity {short count;float weight;float volume;
};
总结
在系统中,内存空间资源是有限的。由于联合的特殊内存使用方式,赋予了它极为高效的内存使用效率,这造就了它在一些特殊情形的极为优秀的应用。可是,“成也萧何,败也萧何”,在联合很大程度上节约内存的同时,联合在同一时间点只能表达一个变量,这导致了它的使用情形比较狭窄,如果没有合理利用,就会有数据丢失的风险。