访问结构联合中结构的第一个字段

Accessing first field of struct in a union of structs

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

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);

关于这个我有 2 个问题:

  1. 是标准要求的联合 总是将他们的内容放在同一个地址?
  2. 如果所有的结构都相同,它会工作吗 字段,仅名称不同?

structunion 的第一个元素保证与 struct´/ 联合本身具有相同的地址值。显然不是同一类型!

对于您的用法,您不需要转换,实际上应该避免它:

6.5.2.3p6: One special guarantee is made in order to simplify the use of unions: if a union contains several structures that share a common initial sequence (see below), and if the union object currently contains one of these structures, it is permitted to inspect the common initial part of any of them anywhere that a declaration of the completed type of the union is visible. …

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

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 包装成 struct:

struct TypeA {
    int x,y;
};

...

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

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

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