典型的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指针.
这可以接受吗?有任何陷阱吗?
最佳答案 有陷阱.
考虑:
#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甚至可能创建陷阱表示.