【问题标题】:Why do we use pointers in self referential structs? [duplicate]为什么我们在自引用结构中使用指针? [复制]
【发布时间】:2018-01-29 21:07:39
【问题描述】:

为什么我们在自引用结构中使用指针?是强制性的还是非强制性的?如果没有,我们在 struct 中使用指向 struct 的指针与普通的 struct 定义相比有什么优势?

typedef struct _Struct {
  struct _Struct* next;  // do we really need this pointer?
} Struct;

【问题讨论】:

  • 如果结构包含自身的实例,则其大小为无穷大。
  • @user3386109 仅当它包含至少一个附加字段时。否则它将只是一个无限的巢,其终端字段将无法访问。
  • 成员 next 是“自引用结构”的奇怪名称。也许发布您看到使用struct _Struct 的上下文。我认为您实际看到的上下文是一个链表。

标签: c pointers struct self-reference


【解决方案1】:

指针的大小是固定的,因此编译器可以在解析时确定结构体_Struct的大小。

如果_Struct在物理上包含自己,则无法确定其大小,这是一个循环定义。

【讨论】:

  • 那么,没有指针就没有办法使用了吗?
  • @AntonBarinov:如果 _Struct 包含 _Struct 和一个 32 位整数,它的大小将是 4 字节 + _Struct。但现在是 8 个字节。不,等等,12字节,16字节等等……这就是为什么必须使用固定大小的指针。
  • @AntonBarinov:C 结构的成员在物理上是结构的一部分,占用的内存与将其定义为单独的变量一样多。结构不能包含自身的实例。 (您可能习惯于其他语言,其中结构的结构成员被实现为隐式引用。C 不这样做。)
  • @ZanLynx 非常感谢。
  • 感谢大家的解释。
【解决方案2】:

结构包含作为外部结构实例的成员是没有意义的。除了要求您声明一个不完整的类型之外,它还将是无限的并且永远不会有足够的字节,因为您添加的每个实例也需要一个实例。

使用指针没问题;但是,例如,这种方法通常用于创建链接列表。指针指向链中的下一个实例。

【讨论】:

    【解决方案3】:

    您不能在结构定义中使用struct _Struct 类型的成员变量,因为它必须是一个完整的类型才能做到这一点。但是在满足声明的} 之前,struct _Struct 是不完整的。

    但是对于指针我们可以这样做,因为指针的大小是相同的,无论是指向完整类型的指针还是不完整类型的指针 - 所以当编译器读取它们时,它可以决定它的大小。 (与它引用自身的情况不同)。

    它必须是指针而不是结构本身,因为类型还不完整 - 不知道它的大小。

    支持我所说的 - 来自standard §6.7.2.1p3

    结构或联合不应包含具有不完整或函数类型的成员(因此,结构不应包含自身的实例,但可能包含指向自身实例的指针),但具有多个命名成员的结构的最后一个成员可能具有不完整的数组类型;这种结构(以及任何可能递归地包含这种结构的成员的联合)不应是结构的成员或数组的元素。

    还有什么时候完成?从§6.7.2.1p8

    结构或联合说明符中的结构声明列表的存在声明了翻译单元内的新类型。 struct-declaration-list 是结构或联合成员的一系列声明。如果 struct-declaration-list 不包含任何命名成员,无论是直接还是通过匿名结构或匿名联合,则行为未定义。 直到终止列表的} 之后,类型才不完整,然后完成。

    如果有人问结构或联合的不完整类型是什么?来自standard §6.2.5p22

    未知内容的结构或联合类型(如 6.7.2.3 中所述)是不完整类型。

    这就是为什么我们不能使用正在声明的结构的实例 - 因为根本不可能知道它的大小。

    【讨论】:

    • 顺便说一句,这是一个好的答案 - 很好地解释了struct _Struct,因为成员仍然不完整
    猜你喜欢
    • 2019-02-16
    • 1970-01-01
    • 2020-11-08
    • 2021-09-17
    • 1970-01-01
    • 1970-01-01
    • 2015-03-10
    • 1970-01-01
    • 2013-09-13
    相关资源
    最近更新 更多