【问题标题】:Pointer to self struct in C指向 C 中的自我结构的指针
【发布时间】:2013-01-14 21:25:19
【问题描述】:

给定以下代码:

typedef struct elementT {
  int data;
  struct elementT *next;
} element;

为什么必须在结构声明本身内执行struct elementT *next 而我不能执行element *next?是因为还没有声明吗?

【问题讨论】:

    标签: c struct typedef


    【解决方案1】:

    typedef 仅在 struct 定义后发生。考虑以下代码;语法无效,但它希望它显示事物的顺序/优先级:

    typedef (struct {
      int field1, field2;
    }) item;
    

    即,struct{...} 是一个表示类型的“表达式”。 typedef 通过给它一个名字来操作那个类型。

    相比之下,

    struct foo {
        foo *next;
    };
    

    之所以起作用,是因为 C 的两个特殊规则:struct <name> 不仅定义了一个类型,而且还给它一个 struct 标记,并且该标记在 struct 声明的其余部分中立即可见(对于显而易见的原因:如果没有这些规则,链表、树等实现起来会非常痛苦)。

    【讨论】:

      【解决方案2】:

      因为C这么说:

      (C99, 6.2.1p7) "[...] 任何其他标识符的范围都在其声明符完成后开始。"

      【讨论】:

      • 不是这样的。在 struct defn 中,elementelement* 都不是不完整的类型——它是一个完全未知的类型名称。
      • 这不是 OP 所要求的。他并没有试图拥有一个包含其自身类型成员的结构,只是一个包含指向其自身类型的指针的结构。问题是为什么他在定义该成员时不能使用 typedef 名称。
      【解决方案3】:

      名称 elementT 是类型名称 struct elementT 的一部分,一旦编译器看到两个标记 struct elementT,就会变得可见(作为不完整的类型),因此您可以在结构定义。

      名称element 是一个typedef 名称,直到出现标识符element 才可见,该标识符位于结构的结尾(结束}之后定义;因此你不能在结构定义中使用它,只是因为它还不存在。

      我个人的偏好(很多非常聪明的人在这一点上与我不同)根本不使用typedef。该类型已经有了一个很好的名字,struct ElementT;为什么要添加第二个?我只想写:

      struct element {
          int data;
          struct element *next;
      };
      

      并将类型称为struct element

      如果你觉得为类型使用一个单词名称就足够有用了,当然,你仍然可以使用 typedef。请记住,直到声明结束后 typedef 名称才可见。并且没有必要使用两个不同的标识符:

      typedef struct element {
          int data;
          struct element *next;
      } element;
      

      现在您可以将类型称为struct elementelement

      (请注意,C++ 有不同的规则;它有效地为struct(或unionclassenum)类型创建了一个隐式类型定义。在C++ 中,typedef 是不必要但无害的.)

      【讨论】:

        【解决方案4】:

        如果将结构声明与其定义分开,则可以实现此行为:

        struct ElementT;                   // not strictly needed
        
        typedef struct ElementT element;   // this declares "struct ElementT" as well
        
        struct ElementT
        {
            element * next;
        };
        

        【讨论】:

        • 是的,但是如果你拼错了ElementT,编译器不会抱怨;它将使 element 成为从未完成的不完整类型的 typedef。
        • @KeithThompson:我想这是真的,但我想你迟早会发现这样的错误。
        猜你喜欢
        • 2021-07-14
        • 2016-08-25
        • 1970-01-01
        • 1970-01-01
        • 2023-04-04
        • 2017-01-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多