代码之家  ›  专栏  ›  技术社区  ›  BeGreen

C中的“未知类型名”嵌套结构[重复]

  •  0
  • BeGreen  · 技术社区  · 6 年前

    我已经很久没有写C了,所以我不知道该怎么做这些递归的事情…我希望每个单元格包含另一个单元格,但在“字段‘child’的类型不完整”行中会出现一个错误。怎么了?

    typedef struct Cell {
      int isParent;
      Cell child;
    } Cell;
    
    0 回复  |  直到 7 年前
        1
  •  163
  •   Jonathan Leffler    16 年前

    显然,一个单元格不能包含另一个单元格,因为它将成为一个永不结束的递归。

    但是,单元格可以包含指向另一个单元格的指针。

    typedef struct Cell {
      bool isParent;
      struct Cell* child;
    } Cell;
    
        2
  •  22
  •   paxdiablo    7 年前

    在C中,不能引用使用结构本身创建的typedef。您必须使用结构名称,如以下测试程序中所示:

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct Cell {
      int cellSeq;
      struct Cell* next; /* 'tCell *next' will not work here */
    } tCell;
    
    int main(void) {
        int i;
        tCell *curr;
        tCell *first;
        tCell *last;
    
        /* Construct linked list, 100 down to 80. */
    
        first = malloc (sizeof (tCell));
        last = first;
        first->cellSeq = 100;
        first->next = NULL;
        for (i = 0; i < 20; i++) {
            curr = malloc (sizeof (tCell));
            curr->cellSeq = last->cellSeq - 1;
            curr->next = NULL;
            last->next = curr;
            last = curr;
        }
    
        /* Walk the list, printing sequence numbers. */
    
        curr = first;
        while (curr != NULL) {
            printf ("Sequence = %d\n", curr->cellSeq);
            curr = curr->next;
        }
    
        return 0;
    }
    

    虽然它可能比标准中的这个复杂得多,但是您可以把它看作是了解 struct Cell 在第一行 typedef 但不知道 tCell 直到最后一行。—)这就是我记忆规则的方式。

        3
  •  15
  •   Sundar    16 年前

    从理论上讲,语言只能支持自引用结构,不能支持自包含结构。

        4
  •  12
  •   Benjamin Horstman    16 年前

    有一种方法可以解决这个问题:

    struct Cell {
      bool isParent;
      struct Cell* child;
    };
    
    struct Cell;
    typedef struct Cell Cell;
    

    如果您这样声明它,它会正确地告诉编译器结构单元和普通的ol'-单元是相同的。所以你可以像正常人一样使用手机。但是仍然必须在初始声明本身内部使用struct cell。

        5
  •  8
  •   Shawn    13 年前

    我知道这篇文章很旧,但是为了达到你想要的效果,你可以尝试以下方法:

    #define TAKE_ADVANTAGE
    
    /* Forward declaration of "struct Cell" as type Cell. */
    typedef struct Cell Cell;
    
    #ifdef TAKE_ADVANTAGE
    /*
       Define Cell structure taking advantage of forward declaration.
    */
    struct Cell
    {
       int isParent;
       Cell *child;
    };
    
    #else
    
    /*
       Or...you could define it as other posters have mentioned without taking
       advantage of the forward declaration.
    */
    struct Cell
    {
       int isParent;
       struct Cell *child;
    };
    
    #endif
    
    /*
        Some code here...
    */
    
    /* Use the Cell type. */
    Cell newCell;
    

    在上面代码片段中提到的两种情况中的任何一种,都必须将子单元格结构声明为指针。如果不这样做,则会得到“字段'child'有不完整类型”错误。原因是必须定义“struct cell”,以便编译器知道使用它时要分配多少空间。

    如果您试图在“struct cell”的定义中使用“struct cell”,那么编译器还不知道“struct cell”应该占用多少空间。然而,编译器已经知道指针占用多少空间,并且(使用forward声明)它知道“cell”是“struct cell”类型(尽管它还不知道“struct cell”有多大)。因此,编译器可以在正在定义的结构中定义一个“cell*”。

        6
  •  3
  •   vineetv2821993    10 年前

    我们来看看typedef的基本定义。typedef用于定义现有数据类型的别名,该数据类型可以是用户定义的,也可以是内置的。

    typedef <data_type> <alias>;
    

    例如

    typedef int scores;
    
    scores team1 = 99;
    

    这里的混淆在于自引用结构,因为同一数据类型的成员没有在前面定义。因此,按照标准方法,您可以将代码编写为:

    //View 1
    typedef struct{ bool isParent; struct Cell* child;} Cell;
    
    //View 2
    typedef struct{
      bool isParent;
      struct Cell* child;
    } Cell;
    
    //Other Available ways, define stucture and create typedef
    struct Cell {
      bool isParent;
      struct Cell* child;
    };
    
    typedef struct Cell Cell;
    

    但是最后一个选项增加了一些额外的行和词,通常我们不想这样做(我们太懒了,你知道;)。所以更喜欢视图2。

        7
  •  2
  •   Keynes    9 年前

    另一个方便的方法是,将结构的结构标记预typedef为:

    //declare new type 'Node', as same as struct tag
    typedef struct Node Node;
    //struct with structure tag 'Node'
    struct Node
    {
    int data;
    //pointer to structure with custom type as same as struct tag
    Node *nextNode;
    };
    //another pointer of custom type 'Node', same as struct tag
    Node *node;
    
        8
  •  1
  •   Yi Jiang G-Man    13 年前

    包含对自身引用的结构。在描述链接列表节点的结构中经常出现这种情况。每个节点都需要对链中的下一个节点的引用。

    struct node
    {
           int data;
           struct node *next; // <-self reference
    };
    
        9
  •  1
  •   m.eldehairy    8 年前

    所有以前的答案都很好,我只是想给出一个解释,为什么一个结构不能包含它自己类型的实例(不是引用)。

    需要注意的是,结构是“值”类型,即它们包含实际值,因此当您声明一个结构时,编译器必须决定分配给它的一个实例的内存量,因此它会遍历它的所有成员,并将它们的内存相加,以计算出整个内存。但如果编译器在结构中找到同一个结构的实例,则这是一个悖论(即为了知道结构A占用多少内存,必须决定结构A占用多少内存!).

    但是引用类型不同,如果结构“a”包含对其自身类型的实例的“引用”,尽管我们还不知道分配给它的内存有多少,但我们知道分配给内存地址的内存有多少(即引用)。

    高温高压