C 访问结构并集中结构的第一个字段

C 访问结构并集中结构的第一个字段,c,struct,unions,memory-alignment,pointer-conversion,C,Struct,Unions,Memory Alignment,Pointer Conversion,我有三个结构共享第一个字段的第一种类型和名称: 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*/ }; 如果我没记错的话,结构的第一个字段必须从与结构本身相同的地址开始 这让我想

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

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);
关于这一点,我有两个问题:

  • 标准是否要求工会 始终将其内容放在同一地址
  • 如果所有结构都具有相同的 菲尔斯,只是名字不同

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

    对于您的使用,您不需要强制转换,实际上应该避免:

    6.5.2.3p6:为简化联合的使用,我们提供了一项特殊保证:如果联合包含多个共享相同初始序列的结构(见下文),并且联合对象当前包含其中一个结构,允许在任何地方检查任何接头的公共初始部分,以确保接头完整类型的声明可见

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

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

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

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

    即使
    struct
    当前包含
    TYPEB
    的值


    另一种更清晰的方法是将
    联合
    包装到
    结构中

    struct TypeA {
        int x,y;
    };
    
    ...
    
    struct data {
        char *name;
        union {
            struct TypeA;
            struct TypeB;
            struct TypeC;
        };
    };
    
    这也在两个级别上使用了gcc扩展:外部
    结构
    联合
    。因此,所有可能的路径都需要唯一的名称。如果希望100%兼容,请按上述方式命名每个成员,并在访问时使用完整路径


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

    C中没有“通用约定”。如果该标准不能保证某些内容,则取决于实现或使用UB。标准确实保证了这一点。真正的问题是:你为什么在乎?演员阵容是个坏主意。使用第一个元素。更好:将普通成员移动到包含的
    结构
    @Olaf是的,我想我在考虑具体实现是如何实现的;但是因为我对标准感兴趣,我就把它删除了。如果没有它,应该更清楚,谢谢。请下层选民解释一下他们的立场好吗?这是今天要问的比较好的C问题之一,伊姆霍。@Bathsheba:这是我不得不承认我投了错误票的少数几个场合之一。我最初认为它太宽泛了(主要是因为现在删除了部分),但在研究了我自己的问题后,看到你的答案,我认为这确实是一个很好的问题。我现在把向下的一票改为向上的一票。对不起,我错了。谢谢你的回答;我仍然是一个初学者,我试图探索类型系统:)可能不相关,但我发现C类型系统非常有趣;我第一次学习C是在我的数学学士学位上,然后转向函数型和依赖型语言,最后通过Rust回到C;这有点冒险,但也很有启发性。
    printf("%s", p->typea.name);
    
    struct TypeA {
        int x,y;
    };
    
    ...
    
    struct data {
        char *name;
        union {
            struct TypeA;
            struct TypeB;
            struct TypeC;
        };
    };