3

我有三个结构共享第一个字段的第一个类型和名称:

struct TYPEA {
  char *name;
  int x,y;   /*or whatever*/
};

struct TYPEB {
  char *name;
  float a[30]; /*or whatever*/
};

struct TYPEC {
  char *name;
  void *w,*z; /*or whatever*/
};

如果我没记错的话,结构的第一个字段必须从与结构本身相同的地址开始。

这让我想知道工会是否同样适用:

union data {
  struct TYPEA;
  struct TYPEB;
  struct TYPEC;
};

union data *p = function_returning_a_sane_default_for_union_data();
printf("%s", (char*) p);

我对此有两个问题:

  1. 标准是否要求工会始终将其内容放在同一地址?
  2. 如果结构都具有相同的字段,那么它会起作用吗?只是名称不同?
4

1 回答 1

3

structa or的第一个元素保证与联合本身union具有相同的地址值。struct´/显然它没有相同的类型!

对于您的使用,您不需要演员表,实际上应该避免它:

6.5.2.3p6:为了简化联合的使用,做了一个特殊的保证:如果一个联合包含多个共享相同初始序列的结构(见下文),并且如果联合对象当前包含这些结构之一,则它是允许在任何可见联合的完整类型声明的任何地方检查它们中任何一个的公共初始部分。…</p>

所以你可以(见下文)简单地

printf("%s", p->name);

(注意:您对未命名union成员的使用不是标准编译器。它是一个(非常有用的)gcc 扩展(-fms-extensions至少 MSVC 也支持)。)

但是:您问题中的代码是错误的。您必须为每个工会成员命名或为每个成员指定类型声明符。但是,对于相同的第一个成员,它不会起作用,因为这些未命名成员的成员的名称必须是唯一的(否则他们应该如何单独访问?)。所以这不会真正起作用。你可以做的是:

union data {
    struct TYPEA typea;
    struct TYPEB typeb;
    struct TYPEC typec;
};

printf("%s", p->typea.name);

即使struct包含TYPEB当前的值。


另一种更清晰的方法是将 包装union成 a struct

struct TypeA {
    int x,y;
};

...

struct data {
    char *name;
    union {
        struct TypeA;
        struct TypeB;
        struct TypeC;
    };
};

这也在两个级别上使用 gcc 扩展:用于外部structunion. 因此,它需要所有可能路径的唯一名称。如果您想 100% 合规,请像上面一样命名每个成员并使用完整的访问路径。

注意:我name从 in 的内部structs 中删除了成员,union并将其移到了外部struct。我也改了名字。C 中唯一被广泛接受的命名约定是只对宏使用全大写。

于 2017-09-11T12:39:59.200 回答