扩展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提供了扩展的结构,但正如here所解释的那样,我们只能将此功能用于匿名定义。然后怎么写
#define BASE_BODY { \
int x; \
}
struct Base BASE_BODY;
struct Derived {
struct BASE_BODY;
int y;
};
然后我可以访问Base成员,因为它是Derived的一部分而没有任何演员或中间成员。如果需要,我可以将Derived指针强制转换为Base指针。
这可以接受吗?有没有陷阱?
答案 0 :(得分:2)
存在陷阱。
考虑:
#define BASE_BODY { \
double a; \
short b; \
}
struct Base BASE_BODY;
struct Derived {
struct BASE_BODY;
short c;
};
在某些实施方面,它可能是sizeof(Base) == sizeof(Derived)
,但是:
struct Base {
double a;
// Padding here
short b;
}
struct Derived {
double a;
short b;
short c;
};
无法保证结构内存布局的开头是相同的。因此,您无法将此类Derived *
传递给期望Base *
的函数,并期望它能够正常工作。
即使填充不会弄乱布局,陷阱预置仍然存在潜在问题:
如果再次sizeof(Base) == sizeof(Derived)
,则c
会终止到Base
末尾的填充所覆盖的区域。将此结构的指针传递给期望Base*
并修改它的函数可能也会影响填充位(填充具有未指定的值),因此可能会破坏c
甚至可能创建陷阱表示。