您的位置:首页 > 编程语言 > C语言/C++

[C专家]分析C语言声明——关于联合

2017-09-06 18:12 288 查看
联合(union)在许多其他语言中被称作变体记录(variant record)。它的外表与结构相似,但在内存布局上存在关键性的区别。在结构中,每个成员依次存储,而在联合中,所有的成员都从偏移地址零开始存储。这样,每个成员的位置都是重叠在一起:在某一时刻,只有一个成员真正存储于该地址。

联合既有一些优点,也有一些缺点。它的缺点就是那些所谓的优点其实并不怎么出色。联合的优点是它的外观同结构一样,只是用关键字union取代了关键字struct。所以,如果你对结构的一切都已了如指掌,基本上也就掌握了联合。联合的一般形式如下:

union 可选的标签
{
类型1 标识符1;
类型2 标识符2;
类型3 标识符3;
}可选的变量定义;
联合一般是作为大型结构的一部分存在的。在有些大型结构中,存在一些与实际表示的数据类型有关的隐式或显示信息。如果存储数据时是一种类型,但在提取该数据时却成了另一种类型,这显然存在着明显的类型不安全性。在Ada中,所有不同类型的字段都显式地存储于记录中,这就避免了这个问题。C语言则含糊得多,让程序员自己去回忆放在那儿的究竟是什么东西。

联合一般被用来节省空间,因为有些数据项是不可能同时出现的,如果同时存储它们,显然颇为浪费。例如,如果我们要存储一些关于动物种类的信息,首先想到的方法可能是:

struct creature
{
char has_backone;
char has_fur;
short num_of_legs_in_exess_of_4;
};
但是,我们知道,所有的动物要么是脊椎动物,要么是无脊椎动物。进而,我们还知道只有脊椎动物才可能有皮毛,只有无脊椎动物才可能有多于4条的腿。没有一种动物既有毛皮又超过4条腿。这样,可以通过把两个相互排斥的字段存储于一个联合中来节省空间:
union secondary_characteristics
{
char has_fur;
shor num_of_legs_in_exess_of_4;
};
struct creature
{
char _has_backone;
union secondary_characteristics form;
};
我们通常采取这种方式来节省备用的存储空间。如果我们有一个数据文件,里面存储了20000000个动物,使用这种方法,可以节省大约20MB的磁盘空间。
然而,联合还有其它用途。联合也可以把同一个数据解释成两种不同的东西,而不是把两个不同的数据解释为同一种东西。非常有意思的是,这种功能跟COBOL中REDEFINES子句一模一样。该用法例子如下:

union bits32_tag
{
int whole; //一个32位的值
struct {char c0,c1,c2,c3;}byte; //4个8位的字节
}values;
这个联合允许程序员提取整个32位值(作为Int),也可以提取单独的字节字段如value.byte.c0等。采用其他方法也能达到这个目的,但联合不需要额外的赋值或强制类型装换。为了找乐,我查看了150000行与机器无关的操作系统源代码。结果显示,结构出现的次数大约是联合的一百倍。这可以提醒你,在实际工作中,你遇见结构的次数将远远多于联合。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: