什么时候应该使用工会?我们为什么需要它们?


当前回答

联合用于节省内存,特别是在内存有限的设备上使用,而内存是很重要的。 经验值:

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;
}

注意:联合的大小是其最大字段的大小,因为必须保留足够的字节来存储大尺寸字段。

其他回答

很难想出需要这种灵活结构的特定场合,也许在发送不同大小消息的消息协议中,但即使在这种情况下,也可能有更好、更适合程序员的替代方案。

联合有点像其他语言中的变体类型——它们一次只能保存一个东西,但这个东西可以是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。

COM接口中使用的VARIANT呢?它有两个字段——“type”和一个包含实际值的联合,该值根据“type”字段进行处理。

有很多用法。只需执行grep union /usr/include/*或类似目录。大多数情况下,联合被包装在结构中,结构的一个成员告诉联合中的哪个元素可以访问。例如,为现实生活的实现签出man elf。

这是基本原则:

struct _mydata {
    int which_one;
    union _data {
            int a;
            float b;
            char c;
    } foo;
} bar;

switch (bar.which_one)
{
   case INTEGER  :  /* access bar.foo.a;*/ break;
   case FLOATING :  /* access bar.foo.b;*/ break;
   case CHARACTER:  /* access bar.foo.c;*/ break;
}

我在为嵌入式设备编码时使用union。我有一个16位的C整数。当我需要从/存储到EEPROM时,我需要检索高8位和低8位。所以我用了这种方法:

union data {
    int data;
    struct {
        unsigned char higher;
        unsigned char lower;
    } parts;
};

它不需要移动,所以代码更容易阅读。

另一方面,我看到一些旧的c++ stl代码使用联合的stl分配器。如果您感兴趣,可以阅读sgi stl源代码。下面是其中的一段:

union _Obj {
    union _Obj* _M_free_list_link;
    char _M_client_data[1];    /* The client sees this.        */
};

一个简单而有用的例子是....

想象一下:

你有一个uint32_t数组[2],想要访问字节链的第3个和第4个字节。 你可以做*((uint16_t*) &数组[1])。 但遗憾的是,这打破了严格的混叠规则!

但是已知的编译器允许你做以下事情:

union un
{
    uint16_t array16[4];
    uint32_t array32[2];
}

严格来说,这仍然是违反规则的。但是所有已知的标准都支持这种用法。