7

在 C 中,是否可以在另一个联合中定义一个联合?如果不是,为什么不可能?或者如果是,它可以在哪里使用?

4

5 回答 5

8

假设您要定义:

union myun {
  int x;
  sometype y;
};

sometype您正在typedef使用的库定义的位置在哪里。如果库碰巧将它实现为联合类型,那么这将是联合中的联合,这是有道理的,因为您不能(从良好的设计角度)违反库类型的封装。

于 2010-09-29T17:01:04.070 回答
4

是的,这是可能的,而且很有用。原因与 Y 中的 X 对 X 和 Y 的许多值有用的原因相同:组合性。程序是通过将微小的组件组​​装成小组件变成大的组件变成巨大的组件变成......有时一堆联合体碰巧组装成一个联合体,那又怎样?

R..'s answer显示了一个在幕后发生的示例:恰好其中一种联合成员类型是联合,但除非您查看库实现,否则您不知道这一点。


编辑但是,请注意,有区别的联合的通用习惯用法,其中联合的每个成员都是一个结构,其第一个字段是包含标记的整数类型,不会扩展到嵌套联合。也就是说,以下是 C 中可区分联合的常见、符合标准 ( N1256 §6.5.2.3.5) 的实现:

struct generic {
    unsigned tag;
};
struct smallnum {
    unsigned tag; /*always TAG_SMALLNUM*/
    unsigned value;
};
struct bignum {
    unsigned tag; /*always TAG_BIGNUM*/
    size_t length;
    unsigned *p;
};
struct string {
    unsigned tag; /*always TAG_STRING*/
    size_t length;
    char *p;
};
union number {
    struct bignum bignum;
    struct smallnum smallnum;
};
union object {
    struct generic generic;
    struct bignum bignum;
    struct smallnum smallnum;
    struct string string;
};

如果您有一个union objectobject ,无论实际分配给该对象的是什么x,您都可以始终将其标签读取为x.generic.tag(或任何其他标签)。x.bignum.tag通过使用对象的唯一标签(鉴别器)。

下面的定义是合法的,但没有用,因为你不能只读取对象的第一个字段union level2来获取标签:如果一个union level2对象写成 a union number,你必须通过number成员读取它的标签,否则你必须读取它的标签通过genericorstring成员标记。如果通过错误的成员访问对每个现有的实现都有效,我不会感到惊讶,但它不符合标准。

union level2 {
    struct generic generic;
    union number number;
    struct string string;
};
于 2010-09-29T19:24:50.850 回答
2

对的,这是可能的。但我倾向于坚持永远不要使用工会的建议。工会是正确答案的情况很少。我怀疑不存在包含工会的工会是一个好主意的情况。

于 2010-09-29T15:56:38.090 回答
1

对的,这是可能的。虽然想出一个人为的例子很容易,但我想不出如何很好地利用我的头顶。

于 2010-09-29T15:57:41.910 回答
0

是的,一个联合可能包含另一个联合:

union foo {
  int x;
  double y;
  union bar {
    char blah[10];
    char *blurga;
  } bletch;
};

不过,我想不出它会有用(甚至是可取的)的情况。

于 2010-09-29T15:58:51.393 回答