什么时候应该使用工会?我们为什么需要它们?
当前回答
低级系统编程就是一个合理的例子。
IIRC中,我使用联合将硬件寄存器分解为组件位。因此,您可以访问一个8位寄存器(在我这样做的那天;-)到组件位。
(我忘记了确切的语法,但是……)这种结构将允许控制寄存器作为control_byte或通过单个位来访问。对于给定的字节顺序,确保位映射到正确的寄存器位是很重要的。
typedef union {
unsigned char control_byte;
struct {
unsigned int nibble : 4;
unsigned int nmi : 1;
unsigned int enabled : 1;
unsigned int fired : 1;
unsigned int control : 1;
};
} ControlRegister;
其他回答
很难想出需要这种灵活结构的特定场合,也许在发送不同大小消息的消息协议中,但即使在这种情况下,也可能有更好、更适合程序员的替代方案。
联合有点像其他语言中的变体类型——它们一次只能保存一个东西,但这个东西可以是int型,浮点型等,这取决于你如何声明它。
例如:
typedef union MyUnion MYUNION;
union MyUnion
{
int MyInt;
float MyFloat;
};
MyUnion将只包含一个int或一个float,这取决于你最近设置的。所以这样做:
MYUNION u;
u.MyInt = 10;
U现在持有int = 10;
u.MyFloat = 1.0;
U现在持有一个等于1.0的浮点数。它不再持有int型。显然,如果你尝试printf("MyInt=%d" u.MyInt);那么你可能会得到一个错误,尽管我不确定具体的行为。
联合的大小由其最大字段的大小决定,在本例中为float。
工会是伟大的。我所见过的联合的一个聪明用法是在定义事件时使用它们。例如,您可能决定一个事件是32位的。
现在,在这32位中,您可能希望将前8位指定为事件发送方的标识符……有时你要把事件作为一个整体来处理,有时你要剖析它并比较它的组成部分。工会让你可以灵活地做到这两点。
union Event { unsigned long eventCode; unsigned char eventParts[4]; };
包含不同记录类型的文件。 包含不同请求类型的网络接口。
看一下这个:X.25缓冲区命令处理
许多可能的X.25命令中的一个被接收到缓冲区中,并通过使用所有可能结构的UNION进行适当的处理。
我想说,它可以更容易地重用可能以不同方式使用的内存,即节省内存。例如,你想做一些“变体”结构体,能够保存一个短字符串以及一个数字:
struct variant {
int type;
double number;
char *string;
};
在32位系统中,这将导致每个变体实例至少使用96位或12个字节。
使用联合可以将大小减小到64位或8字节:
struct variant {
int type;
union {
double number;
char *string;
} value;
};
如果你想添加更多不同的变量类型,你甚至可以保存更多。这可能是真的,你可以做类似的事情,强制转换一个空指针-但联合使它更容易访问,以及类型安全。这样的节省听起来并不是很大,但是您节省了用于该结构的所有实例的三分之一的内存。
我在几个库中看到过它作为面向对象继承的替代品。
E.g.
Connection
/ | \
Network USB VirtualConnection
如果你想让Connection“类”是上面的任何一个,你可以这样写:
struct Connection
{
int type;
union
{
struct Network network;
struct USB usb;
struct Virtual virtual;
}
};
libinfinity示例:http://git.0x539.de/?p=infinote.git;a=blob;f=libinfinity/common/inf-session.c;h=3e887f0d63bd754c6b5ec232948027cbbf4d61fc;hb=HEAD#l74