什么时候应该使用工会?我们为什么需要它们?
当前回答
这里有一个来自我自己代码库的联合的例子(来自记忆和转述,所以可能不准确)。它被用来在我构建的解释器中存储语言元素。例如,以下代码:
set a to b times 7.
由以下语言元素组成:
[设置]符号 可变[a] 符号[到] 可变[b] 符号[时报] 康斯坦[7] 符号[。]
语言元素被定义为“#define”值,如下:
#define ELEM_SYM_SET 0
#define ELEM_SYM_TO 1
#define ELEM_SYM_TIMES 2
#define ELEM_SYM_FULLSTOP 3
#define ELEM_VARIABLE 100
#define ELEM_CONSTANT 101
下面的结构被用来存储每个元素:
typedef struct {
int typ;
union {
char *str;
int val;
}
} tElem;
然后,每个元素的大小是最大联合的大小(typ为4字节,联合为4字节,尽管这些是典型值,但实际大小取决于实现)。
为了创建一个“set”元素,你可以使用:
tElem e;
e.typ = ELEM_SYM_SET;
为了创建一个“variable[b]”元素,你可以使用:
tElem e;
e.typ = ELEM_VARIABLE;
e.str = strdup ("b"); // make sure you free this later
为了创建一个常量[7]元素,你可以使用:
tElem e;
e.typ = ELEM_CONSTANT;
e.val = 7;
你可以很容易地将其扩展为包含浮点数(float flt)或有理数(struct ratnl {int num;Int denom;})和其他类型。
基本前提是str和val在内存中不是连续的,它们实际上是重叠的,所以这是一种在同一块内存上获得不同视图的方法,如图所示,其中结构基于内存位置0x1010,整数和指针都是4字节:
+-----------+
0x1010 | |
0x1011 | typ |
0x1012 | |
0x1013 | |
+-----+-----+
0x1014 | | |
0x1015 | str | val |
0x1016 | | |
0x1017 | | |
+-----+-----+
如果只是在一个结构中,它看起来会是这样的:
+-------+
0x1010 | |
0x1011 | typ |
0x1012 | |
0x1013 | |
+-------+
0x1014 | |
0x1015 | str |
0x1016 | |
0x1017 | |
+-------+
0x1018 | |
0x1019 | val |
0x101A | |
0x101B | |
+-------+
其他回答
工会是伟大的。我所见过的联合的一个聪明用法是在定义事件时使用它们。例如,您可能决定一个事件是32位的。
现在,在这32位中,您可能希望将前8位指定为事件发送方的标识符……有时你要把事件作为一个整体来处理,有时你要剖析它并比较它的组成部分。工会让你可以灵活地做到这两点。
union Event { unsigned long eventCode; unsigned char eventParts[4]; };
当您希望对由硬件、设备或网络协议定义的结构进行建模时,或者当您要创建大量对象并希望节省空间时,可以使用联合。不过,在95%的情况下,你真的不需要它们,坚持使用易于调试的代码。
联合用于节省内存,特别是在内存有限的设备上使用,而内存是很重要的。 经验值:
union _Union{
int a;
double b;
char c;
};
For example,let's say we need the above 3 data types(int,double,char) in a system where memory is limited.If we don't use "union",we need to define these 3 data types. In this case sizeof(a) + sizeof(b) + sizeof(c) memory space will be allocated.But if we use onion,only one memory space will be allocated according to the largest data t ype in these 3 data types.Because all variables in union structure will use the same memory space. Hence the memory space allocated accroding to the largest data type will be common space for all variables. For example:
union _Union{
int a;
double b;
char c;
};
int main() {
union _Union uni;
uni.a = 44;
uni.b = 144.5;
printf("a:%d\n",uni.a);
printf("b:%lf\n",uni.b);
return 0;
}
输出是: 答:0 和b: 144.500000
为什么a是0 ?因为联合结构只有一个内存区域,而所有数据结构都共同使用它。最后一个赋值覆盖了旧值。 再举一个例子:
union _Union{
char name[15];
int id;
};
int main(){
union _Union uni;
char choice;
printf("YOu can enter name or id value.");
printf("Do you want to enter the name(y or n):");
scanf("%c",&choice);
if(choice == 'Y' || choice == 'y'){
printf("Enter name:");
scanf("%s",uni.name);
printf("\nName:%s",uni.name);
}else{
printf("Enter Id:");
scanf("%d",&uni.id);
printf("\nId:%d",uni.id);
}
return 0;
}
注意:联合的大小是其最大字段的大小,因为必须保留足够的字节来存储大尺寸字段。
在学校里,我是这样使用联合的:
typedef union
{
unsigned char color[4];
int new_color;
} u_color;
我用它来更容易地处理颜色,而不是使用>>和<<操作符,我只需要遍历我的char数组的不同索引。
我在几个库中看到过它作为面向对象继承的替代品。
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