何时使用联合以及何时使用结构

问题描述 投票:0回答:4

我知道联合和结构之间的区别。 但从设计和编码的角度来看,使用联合而不是结构的各种用例是什么?一是空间优化。使用它们还有其他好处吗?

c structure unions
4个回答
10
投票

实际上只有两个主要用途。首先是创建一个歧视性工会。这可能就是您所想到的“空间优化”,但还有更多内容。您需要额外的数据位来了解联合的哪个成员是“活动的”(其中包含有效数据),因为编译器不会为您执行此操作。您通常会看到类似的代码在结构内部有一个联合,例如:

struct mixed {
  enum { TYPE_INT, TYPE_FLOAT } type;
  union {
    int    int_value;
    float  float_value;
  } data;
};

当分配给 data.int_value 或 data.float_value 时,您还需要将类型成员设置为适当的枚举值。然后使用混合值的代码可以确定是读取 int_value 还是 float_value。

联合的第二个重要用途是提供一个 API,允许用户以多种方式访问相同的数据。这是相当有限的,因为它要求联合中的所有类型以相同的方式放置在内存中。例如,int 和 float 完全不同,将 float 作为整数访问不会给您任何特别有意义的数据。

有关此用例的有用示例,请查看有多少网络 API 将为 IPv4 地址定义联合,例如:

union ipv4addr {
  unsigned  address;
  char      octets[4];
};

大多数代码只想传递 32 位整数值,但有些代码想要读取各个八位位组(字节)。这一切都可以通过指针强制转换来实现,但它更容易一些,更自我记录,因此以这种方式使用联合稍微安全一些。

但总的来说,如果您不确定是否需要工会,那么您几乎肯定不需要工会。


7
投票

当您的“事物”可以是许多不同事物之一但一次只能是一个时,您可以使用联合。

当你的“事物”应该是一组其他事物,并且所有这些事物可以同时存在时,你就使用结构。

例如,联合可用于表示小部件

小玩意(带有一个字段让我们知道它是什么),可以看起来像:

struct { // +-----------+ int is_widget; // | is_widget | | union { // +-----------+ | increasing widget w; // | w | g | | memory gizmo g; // +-----+ | | addresses } // | | V } // +-----+
在这个例子中,

w

g
会在内存中重叠,你可以在评论的右侧看到(这个例子中的小玩意更大)。

我已经在编译器中看到过这种用法,其中标记可以是数字常量、关键字、变量名、字符串和许多其他词汇元素(但是,当然,每个标记只是其中的

一个,你不能拥有一个既是变量名又是数字常量的标记)。

或者,在没有小部件的情况下处理小玩意可能是非法的,在这种情况下,您可以使用:

struct { // +-----+ widget w; // | w | | gizmo g; // +-----+ | increasing } // | g | | memory // | | | addresses // | | V // +-----+
在这种情况下,

g

将位于不同的内存位置,位于
w
之后的某个位置(无重叠)。

这种情况的用例比比皆是,例如包含电话簿应用程序记录布局的结构,这无疑将为您从您首选的应用程序商店赚取数百万美元:-)


请注意,从技术上讲,我不确定它们是否需要在联合中重叠,这只是最有可能的情况(而且我也没有在其中显示任何填充,这也是一种可能性)。

实现可以将它们连续地放入内存中,因为编译器只需要表现得“好像”它们重叠,例如,如果您在设置 w

后尝试访问

g

,则会发出抱怨。
但是,编译器这样做是不寻常的,因为它忽略了内存效率。

在某些情况下,我们可能一次只能使用一个变量,但不同的结果必须使用不同的名称存储。在这种情况下,联合将通过在具有最大变量大小的一个位置为每个变量分配相同的空间来提供帮助。

0
投票
即,如果我们使用 int 和 char,那么 union 将为具有更大大小的 char 分配空间,并且 int 也将存储在同一空间中,覆盖最后一个空间。

你不能将联合与结构进行比较,就像将苹果与橙子进行比较一样,它们用于不同的事物。联合通常用于空间宝贵的情况,但更重要的是用于专门的备用数据。联合有助于消除拼写错误并确保互斥状态保持互斥,因为当我们对互斥数据使用联合时,编程逻辑中的错误会更快地显现出来。

0
投票
当处理组件之间的复杂数据传递时,联合可以使指针数学变得更加容易。例如,当使用 LEX 和 YACC 开发编译器时,值会以联合形式从词法分析器传递到解析器。由于使用了 union,解析器的实现和后续的类型转换变得更加容易。

© www.soinside.com 2019 - 2024. All rights reserved.