在C11匿名结构定义中使用宏

在C11匿名结构定义中使用宏,c,macros,struct,coding-style,c11,C,Macros,Struct,Coding Style,C11,扩展stuct的典型C99方法如下 struct Base { int x; /* ... */ }; struct Derived { struct Base base_part; int y; /* ... */ }; 然后我们可以将struct-Derived*的实例强制转换为struct-Base*,然后访问x 我想访问struct-Derived*obj直接,例如obj->x和obj->y。C11提供扩展结构,但正如前面所解释的,我们只能在匿

扩展stuct的典型C99方法如下

struct Base {
    int x;
    /* ... */
};

struct Derived {
    struct Base base_part;
    int y;
    /* ... */
};
然后我们可以将
struct-Derived*
的实例强制转换为
struct-Base*
,然后访问
x

我想访问
struct-Derived*obj直接,例如obj->x和obj->y。C11提供扩展结构,但正如前面所解释的,我们只能在匿名定义中使用此功能。那我们写一篇怎么样

#define BASE_BODY { \
    int x; \
}

struct Base BASE_BODY;

struct Derived {
    struct BASE_BODY;
    int y;
};
然后我可以访问基本成员,就像它是派生的一部分一样,而不需要任何类型转换或中间成员。如果需要,我可以将派生指针转换为基指针

这可以接受吗?有陷阱吗?

有陷阱

考虑:

#define BASE_BODY { \
    double a; \
    short b; \
}

struct Base BASE_BODY;

struct Derived {
    struct BASE_BODY;
    short c;
};
在某些实现中,可能是
sizeof(Base)==sizeof(派生)
,但是:

struct Base {
    double a;
    // Padding here
    short b;
}

struct Derived {
    double a;
    short b;
    short c;
};
无法保证结构的开头内存布局是相同的。因此,您不能将这种
派生的*
传递给期望
基*
的函数,并期望它工作

即使填充不会弄乱布局,陷阱预安装仍然存在潜在问题:


如果再次
sizeof(Base)==sizeof(Derived)
,但是
c
结束到
Base
末尾的填充所覆盖的区域。将此结构的指针传递给需要
Base*
并对其进行修改的函数,也可能会影响填充位(填充具有未指定的值),从而可能损坏
c
,甚至可能创建陷阱表示。

这是真的。在结构定义和上行的可怕破坏结果之前,我放置了不同的语法包。作为替代,您可以考虑使用<代码> TyPufF(见答案),通过<代码> -FMS扩展< /代码>选项在<代码> GCC < /代码>或<代码> CLAN<代码>中,但它是非标准的。