为什么联合会以这种方式使用?

时间:2011-08-09 14:47:10

标签: c unions

联盟中的成员不是独家的,如果你已经引用了其中一个,你就不能引用另一个吗?

union Ptrlist
{
    Ptrlist *next;
    State *s;
};

void
patch(Ptrlist *l, State *s)
{
    Ptrlist *next;

    for(; l; l=next){
        next = l->next;
        l->s = s;
    }
}

但上述同时指代nexts,任何人都可以解释这个问题吗?

7 个答案:

答案 0 :(得分:5)

联盟只定义

&l->next == &l->s 

就是这样。首次访问没有语言限制。

答案 1 :(得分:2)

正如其他人已经指出的那样,所有成员在所有时都处于活动状态。唯一要考虑的是成员是否都处于有效状态。

如果你想要某种程度的排他性,你需要一个标记的联盟。基本思想是将union包装在一个struct中,struct有一个成员标识应该使用union中的哪个元素。举个例子:

enum Tag {
    FIRST,
    SECOND
};

struct {
    Tag tag;
    union {
        int First;
        double Second;
    };
} taggedUnion;

现在taggedUnion可以像:

一样使用
if(taggedUnion.tag == FIRST)
    // use taggedUnion.First;
else
    // use taggedUnion.Second

答案 2 :(得分:1)

您正在从next执行l->next的作业。然后,您通过作业l->s“覆盖”l->s = s

当您分配到l->s时,它会覆盖l->next中保留的内存。如果nexts的“大小”相同,则两者可能同时处于“有效”状态。

答案 3 :(得分:1)

是的,它应该是那样的。 * s和* next都指向相同的内存位置。而且你可以同时使用它们......它们并不是唯一的。

答案 4 :(得分:1)

不,这不是真的。您可以随时使用union的任何成员,但如果您读取的成员不是最近编写的成员,那么结果会有点复杂。但是,在您的代码示例中甚至没有发生这种情况,并且它绝对没有任何问题。对于列表中的每个项目,将读取其next成员,然后编写其s成员,覆盖其next

答案 5 :(得分:0)

有关工会的介绍性讨论,请参阅http://publications.gbdirect.co.uk/c_book/chapter6/unions.html

基本上,这是一种提前进行打字的简单方法。所以,而不是

int query_my_data(void *data, int data_len) {
  switch(data_len) {
    case sizeof(my_data_t): return ((my_data_t *)data)->value;
    case sizeof(my_other_data_t): return ((my_other_data_t *)data)->other_val;
    default: return -1;
  }

你可以通过

来简化它
typedef struct {
  int data_type;
  union {
    my_data_t my_data;
    my_other_data_t other_data;
  } union_data;
} my_union_data_t;

int query_my_data(my_union_data_t *data) {
  switch(data->data_type) {
    case TYPE_MY_DATA: return data->union_data.my_data.value;
    case TYPE_MY_OTHER_DATA: return data->union_data.other_data.other_val;
    default: return -1;
  }

my_data和other_data在内存中的起始地址相同。

答案 6 :(得分:0)

union类似于struct,但它只为变量分配内存。 union的大小将等于存储在其中的最大类型的大小。例如:

union A {
    unsigned char c;
    unsigned short s;
};

int sizeofA = sizeof(A); // = 2 bytes

union B {
    unsigned char c[4];
    unsigned short s[2];
    unsigned int i;
};

int sizeofB = sizeof(B); // = 4 bytes

在第二个示例中,s[0] == (c[1] << 8) & #ff00 | c[0];。变量c,s和i重叠。

B b;
// This assignment
b.s[0] = 0;
// is similar to:
b.c[0] = 0;
b.c[1] = 0;

union仅限于原始类型和指针。在C ++中,您不能在联合中存储类。所有其他规则基本上与结构相同,例如公共访问,堆栈分配等。

因此,在您的示例中,您必须使用结构而不是联合。