首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >多层次的“结构继承”保证在任何地方都能工作吗?

多层次的“结构继承”保证在任何地方都能工作吗?
EN

Stack Overflow用户
提问于 2020-04-06 12:29:43
回答 2查看 192关注 0票数 3

我知道在C中,结构的第一个成员保证在它之前没有填充。因此,&mystruct == &mystruct.firstmember总是正确的。

这允许"struct继承“技术,as described in this question

代码语言:javascript
运行
复制
typedef struct
{
    // base members

} Base;

typedef struct
{
    Base base;

    // derived members

} Derived;

// ... later
Base* object = (Base*) malloc(sizeof()); // This is legal

但是,我想确保这实际上在无限层的“继承”中安全地工作。例如:

代码语言:javascript
运行
复制
typedef struct
{
    // members

} A;

typedef struct
{
    A base;

    // members

} B;

typedef struct 
{
    B base;

    // members
} C;

以下所有的用途是否都能正常工作?

代码语言:javascript
运行
复制
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标准工作?

代码语言:javascript
运行
复制
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
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-04-11 16:54:07

你所描述的那种“多层次继承”必须遵循同样的原则--在你提到的其他问答中解释过--这使得这种继承完全可行。具体而言,该标准明确规定,在适用的类型之间转换结构及其初始成员的地址具有所希望的效果:

指向结构对象的指针,经过适当转换,指向其初始成员.反之亦然。

(第6.7.2.1/15号决议)

因此,考虑这一声明,相对于所提供的结构定义:

代码语言:javascript
运行
复制
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)访问动态分配的空间,我看没有任何场景支持对动态分配情况的标准的不同解释。实际上,我并不期望任何实现都需要通过最特定类型的初始访问。

票数 4
EN

Stack Overflow用户

发布于 2020-04-11 16:52:17

ISO C标准所要求的工作情况如下:

代码语言:javascript
运行
复制
union U {
  struct X x;
  struct Y y;
  struct Z z;
  /* ... */
};

如果结构共享一些公共的初始成员序列,那么该初始序列可以通过任何成员访问。例如:

代码语言:javascript
运行
复制
 struct X {
   /* common members, same as in Y and Z: */
   int type;
   unsigned flags;

   /* different members */
 };

如果所有结构都具有相同的顺序和类型的typeflags,则需要这样做:

代码语言:javascript
运行
复制
union U u;
u.x.type = 42;  /* store through x.type */
foo(u.y.type);  /* access through y.type */

其他这类黑客不受ISO C的“祝福”。

你现在的情况有点不同。问题是,给定一个结构的主导成员,我们是否可以将指向该成员类型的结构的指针转换为该成员的类型,然后使用它。最简单的例子是这样的:

代码语言:javascript
运行
复制
struct S {
  int m;
};

给定一个对象struct S s,我们可以使用&s.m获取m的地址,获得一个int *指针。等价地,我们可以使用(int *) &s获得相同的指针。

ISO C确实要求结构具有与其第一个成员相同的地址;指向结构的指针和指向第一个成员的指针具有不同的类型,但指向相同的地址,我们可以在它们之间进行转换。

这不受嵌套级别的限制。给定这种类型的a

代码语言:javascript
运行
复制
struct A {
  struct B {
    struct C {
       int m;
    } c;
  } b
};

地址&a.b.c.m仍然与地址&a相同。指针&a.b.c.m(int *) &a相同。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61059895

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档