我知道在C中,结构的第一个成员保证在它之前没有填充。因此,&mystruct == &mystruct.firstmember总是正确的。
这允许"struct继承“技术,as described in this question。
typedef struct
{
// base members
} Base;
typedef struct
{
Base base;
// derived members
} Derived;
// ... later
Base* object = (Base*) malloc(sizeof()); // This is legal但是,我想确保这实际上在无限层的“继承”中安全地工作。例如:
typedef struct
{
// members
} A;
typedef struct
{
A base;
// members
} B;
typedef struct
{
B base;
// members
} C;以下所有的用途是否都能正常工作?
A* a = (A*) malloc(sizeof(B));
A* a = (A*) malloc(sizeof(C));
B* b = (B*) malloc(sizeof(C));
C* c = malloc(sizeof(C));
// ... use and access members through the pointers编辑:
让我澄清一下我在问什么。以下使用的“多级继承”是否保证按照C标准工作?
C* c = malloc(sizeof(C));
// ... initialize fields in c
A* a = (A*) c;
// ... use A fields in a
B* b = (B*) a;
// ... use B fields in b
B* b = (B*) c;
// ... use B fields in b
c = (C*) a;
// ... go back to using C fields in c发布于 2020-04-11 16:54:07
你所描述的那种“多层次继承”必须遵循同样的原则--在你提到的其他问答中解释过--这使得这种继承完全可行。具体而言,该标准明确规定,在适用的类型之间转换结构及其初始成员的地址具有所希望的效果:
指向结构对象的指针,经过适当转换,指向其初始成员.反之亦然。
(第6.7.2.1/15号决议)
因此,考虑这一声明,相对于所提供的结构定义:
C c;引用的条款规定,&c == (C *) &c.base和(B *) &c == &c.base都是真实的。
但是c.base是一个B,所以该条款还规定(A *) &c.base == &c.base.base和&c.base == (B *) &c.base.base都是真的。
因为(B *) &c == &c.base是真,&c.base == (B *) &c.base.base也是真,所以(B *) &c == (B *) &c.base.base也是真。
将两边都浇铸到A *或C *中,然后生成(A *) &c == &c.base.base和&c == (C *) &c.base.base相等的值。
这种推理可以扩展到任意嵌套深度。
对于严格的混叠规则来说,动态分配的结构可以稍微吹毛求疵,但是没有理由认为在这种情况下它的工作方式会有任何不同,而且只要一个人首先通过最特定类型的lvalue (本例中的C)访问动态分配的空间,我看没有任何场景支持对动态分配情况的标准的不同解释。实际上,我并不期望任何实现都需要通过最特定类型的初始访问。
发布于 2020-04-11 16:52:17
ISO C标准所要求的工作情况如下:
union U {
struct X x;
struct Y y;
struct Z z;
/* ... */
};如果结构共享一些公共的初始成员序列,那么该初始序列可以通过任何成员访问。例如:
struct X {
/* common members, same as in Y and Z: */
int type;
unsigned flags;
/* different members */
};如果所有结构都具有相同的顺序和类型的type和flags,则需要这样做:
union U u;
u.x.type = 42; /* store through x.type */
foo(u.y.type); /* access through y.type */其他这类黑客不受ISO C的“祝福”。
你现在的情况有点不同。问题是,给定一个结构的主导成员,我们是否可以将指向该成员类型的结构的指针转换为该成员的类型,然后使用它。最简单的例子是这样的:
struct S {
int m;
};给定一个对象struct S s,我们可以使用&s.m获取m的地址,获得一个int *指针。等价地,我们可以使用(int *) &s获得相同的指针。
ISO C确实要求结构具有与其第一个成员相同的地址;指向结构的指针和指向第一个成员的指针具有不同的类型,但指向相同的地址,我们可以在它们之间进行转换。
这不受嵌套级别的限制。给定这种类型的a:
struct A {
struct B {
struct C {
int m;
} c;
} b
};地址&a.b.c.m仍然与地址&a相同。指针&a.b.c.m与(int *) &a相同。
https://stackoverflow.com/questions/61059895
复制相似问题