简体   繁体   English

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

[英]Using macro in C11 anonymous struct definition

The typical C99 way to extending stuct is something like 典型的C99扩展结构的方式就像

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

struct Derived {
    struct Base base_part;
    int y;
    /* ... */
};

Then we may cast instance of struct Derived * to struct Base * and then access x . 然后我们可以将struct Derived *实例转换为struct Base *然后访问x

I want to access base elements of struct Derived * obj; 我想访问struct Derived * obj;基本元素struct Derived * obj; directly, for example obj->x and obj->y. 直接,例如obj-> x和obj-> y。 C11 provide extended structs, but as explained here we can use this feature only with anonymous definitions. C11提供了扩展的结构,但正如这里所解释的我们只能将此功能用于匿名定义。 Then how about to write 然后怎么写

#define BASE_BODY { \
    int x; \
}

struct Base BASE_BODY;

struct Derived {
    struct BASE_BODY;
    int y;
};

Then I may access Base members same as it's part of Derived without any casts or intermediate members. 然后,我可以访问Base成员,因为它是Derived的一部分而没有任何演员或中间成员。 I can cast Derived pointer to Base pointer if need do. 如果需要,我可以将Derived指针强制转换为Base指针。

Is this acceptable? 这可以接受吗? Are there any pitfalls? 有任何陷阱吗?

There are pitfalls. 有陷阱。

Consider: 考虑:

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

struct Base BASE_BODY;

struct Derived {
    struct BASE_BODY;
    short c;
};

On some implementation it could be that sizeof(Base) == sizeof(Derived) , but: 在某些实现中,它可能是sizeof(Base) == sizeof(Derived) ,但是:

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

struct Derived {
    double a;
    short b;
    short c;
};

There is no guarantee that at the beginning of the struct memory layout is the same. 无法保证结构内存布局的开头是相同的。 Therefore you cannot pass this kind of Derived * to function expecting Base * , and expect it to work. 因此,您无法将此类Derived *传递给期望Base *函数,并期望它能够正常工作。

And even if padding would not mess up the layout, there is a still potential problem with trap presenstation: 即使填充不会弄乱布局,陷阱预置仍然存在潜在问题:

If again sizeof(Base) == sizeof(Derived) , but c ends up to a area which is covered by the padding at the end of Base . 如果sizeof(Base) == sizeof(Derived) ,则c结束到Base末尾的填充所覆盖的区域。 Passing pointer of this struct to function which expects Base* and modifies it, might affect padding bits too (padding has unspecified value), thus possibly corrupting c and maybe even creating trap presentation. 将此结构的指针传递给期望Base*并修改它的函数,也可能影响填充位(填充具有未指定的值),因此可能破坏c甚至可能创建陷阱表示。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM