何时使用联合体,何时使用结构体

发布于 2024-12-13 03:31:41 字数 72 浏览 3 评论 0原文

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

I know the differences between union and structure.
But from a design and coding perspective what are the various use cases of using a union instead of a structure? One is a space optimization. Are there any more advantages of using them?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

腹黑女流氓 2024-12-20 03:31:41

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

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 位整数值,但有些代码想要读取各个八位字节(字节) )。这一切都可以通过指针强制转换来实现,但它更容易一些,更具自记录性,因此以这种方式使用联合稍微安全一些。

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

There's really only two major uses. The first is to create a discriminated union. That's probably what you were thinking of by "space optimization," but there's a bit more to it. You need an extra bit of data to know which member of the union is "alive" (has valid data in it) since the compiler does not do this for you. You'd usually see code like that having a union inside of a struct, something like:

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

When assigning to either data.int_value or data.float_value, you'd be expected to set the type member to the appropriate enumeration value as well. Then your code using the mixed value can figure out whether to read the int_value or float_value.

The second significant use of unions is to offer an API that allows the user to access the same data multiple ways. This is pretty limited, as it requires all types in the union to be laid in memory in identical ways. For example, an int and a float are entirely different, and accessing a float as an integer does not give you any particularly meaningful data.

For a useful example of this use case, see how many networking APIs will define a union for IPv4 addresses, something like:

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

Most code just wants to pass around the 32-bit integer value, but some code wants to read the individual octets (bytes). This is all doable with pointer casts, but it's a bit easier, more self-documenting, and hence slightly safer to use a union in such a fashion.

In general though, if you're not sure if you need a union, you almost certainly do not need one.

紅太極 2024-12-20 03:31:41

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

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

例如,联合可用于表示小部件小玩意(带有一个允许我们知道它是什么的字段),可以看起来像:

struct {            // +-----------+
    int is_widget;  // | is_widget |  |
    union {         // +-----------+  | increasing
        widget w;   // |  w  |  g  |  |  memory
        gizmo g;    // +-----+     |  |   addresses
    }               //       |     |  V
}                   //       +-----+

在此示例中,wg 将在内存中重叠,您可以在注释的右侧看到(本例中的小控件更大)。

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

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

struct {       // +-----+
    widget w;  // |  w  |  |
    gizmo g;   // +-----+  | increasing
}              // |  g  |  |  memory
               // |     |  |   addresses
               // |     |  V
               // +-----+

在这种情况下,g将位于不同的内存位置,在w(无重叠)。

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


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

实现可以将它们连续地放入内存中,因为编译器只需要“好像”它们重叠一样,例如,如果您在设置 g 后尝试访问 w ,则会发出抱怨。

然而,编译器这样做是不寻常的,因为它忽略了内存效率。

You use a union when your "thing" can be one of many different things but only one at a time.

You use a structure when your "thing" should be a group of other things, all of which can exist concurrently.

For example, a union can be used for representing widgets or gizmos (with a field allowing us to know what it is), can look something like:

struct {            // +-----------+
    int is_widget;  // | is_widget |  |
    union {         // +-----------+  | increasing
        widget w;   // |  w  |  g  |  |  memory
        gizmo g;    // +-----+     |  |   addresses
    }               //       |     |  V
}                   //       +-----+

In this example, w and g will overlap in memory, you can see that on the right in the comment (gizmos are bigger in this example).

I've seen this used in compilers where a token can be a numeric constant, keyword, variable name, string, and many other lexical elements (but, of course, each token is only one of those things, you cannot have a single token that is both a variable name and a numeric constant).

Alternately, it may be illegal for you to process gizmos without widgets, in which case you could use:

struct {       // +-----+
    widget w;  // |  w  |  |
    gizmo g;   // +-----+  | increasing
}              // |  g  |  |  memory
               // |     |  |   addresses
               // |     |  V
               // +-----+

In this case, g would be at a distinct memory location, somewhere after w (no overlap).

Use cases for this abound, such as structures containing record layouts for your phone book application which will no doubt earn you gazillions of dollars from your preferred app store :-)


Note that, technically, I'm not sure they are required to overlap in a union, that's just the most likely case (and I also don't show any padding in there which is also a possibility).

An implementation could put them consecutively in memory since a compiler only needs to act "as if" they overlap, complaining if you try to access w after setting g, for example.

However, it would be unusual for a compiler to do that, since it ignores memory efficiencies.

滴情不沾 2024-12-20 03:31:41

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

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

Ins some cases we may have to use only one variable at a time but the different results will have to be stored with different names. In such cases union will help by allocating same space for each variable at one location with the maximum variable size.

i.e if we use int and char then union will allocate space for char which has the bigger size and the int too 'll be stored in the same space overriding the last one.

撩动你心 2024-12-20 03:31:41

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

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

You cannot compare unions to structures, it's like comparing apples to oranges, they are used for different things. Unions are typically used in situations where space is premium but more importantly for exclusively alternate data. Unions help eliminate typos and ensure that mutually exclusive states remain mutually exclusive because error in programming logic will surface more quickly when we use unions for mutually exclusive data.

Also unions can lead to much easier pointer mathematics when working with complex data passing between components. case-in-point when developing compilers with LEX and YACC the values are passed from the lexer to the parser in a union. The parser implementation and subsequent typecasting is made significantly easier because of the use of union.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文