Working with a union of structs in C

2019-04-28 09:54发布

Say I have the following types:

typedef struct TYPEA
{
    int type;
    char[12] id;
} TYPEA;

typedef struct TYPEB
{
    int type;
    int value;
} TYPEB;

I want to use create a union of these types and 'int', so that I can access the "type" int without needing to know whether TYPEA or TYPEB is stored in the union (the value of int lets me determine which is actually stored there). I can't get the right syntax though.

My union:

typedef union MEMBER
{
    int type;
    struct TYPEA a;
    struct TYPEB b;
} MEMBER;

The union is accessed via:

typedef struct WRAPPER
{
    union MEMBER* member;
    struct WRAPPER* next;
} WRAPPER;

Questions:

  1. (With 'w' as a pointer to an allocated WRAPPER struct) Accessing using w->member->a.id gives "request for member 'id' in something not a structure or union.
  2. Can I assign a pointer to an already malloc'd TYPEA/B to w->member directly? Or does a union need to be malloced specially?

Thanks.

标签: c unions
4条回答
我想做一个坏孩纸
2楼-- · 2019-04-28 10:07

You might want to check out the code in my question:

Union of structs with common first member

Essentially, I do what you want but I'm using an inner struct (contained in the example) that's common to the two types. This struct can then be cast to gain access to the common elements of both types.

查看更多
该账号已被封号
3楼-- · 2019-04-28 10:16
  1. You defined the member field as a pointer, so you should use w->member->type instead of w->member.type.
  2. You should malloc the union type. When you allocate a union, you'll get a structure that has a sizeof equal to the largest element in the union. If you try to copy structures into union pointers, you'll mess up the alignment.
查看更多
我欲成王,谁敢阻挡
4楼-- · 2019-04-28 10:23

w->member.type should be w->member->type because w->member is a pointer.

I don't know off the top of my head whether C will let you assign a TYPEA* or TYPEB* to a MEMBER* - somehow I doubt it. You can always (MEMBER*) it, but I would consider recomposing the structs to remove the int tag and instead declare one struct that includes the tag and a union of TYPEA and TYPEB. The structs ideally shouldn't need to be concerned with the fact that they're in a union.

查看更多
做自己的国王
5楼-- · 2019-04-28 10:24
  1. Use w->member->type.
  2. You need to allocate the union specifically.

One note that may be a point of misunderstanding is that the union holds EITHER the int, or TYPEA, or TYPEB, so in particular you cannot rely on your int type; in the union to tell you which struct the union holds.

Edit to respond to question in comments:

You probably want something like this:

struct TYPEA {
  char data[30]; // or whatever
};

struct TYPEB {
  double x, y; // or whatever
};

struct some_info {
  int type; // set accordingly
  union {
    struct TYPEA a;
    struct TYPEB b;
  } data; // access with some_info_object.data.a or some_info_object.data.b
};
查看更多
登录 后发表回答