wake-up-neo.com

Selbstreferenzielle Strukturdefinition?

Ich habe nicht sehr lange C geschrieben und bin mir daher nicht sicher, wie ich diese Art von rekursiven Dingen ausführen soll ... Ich möchte, dass jede Zelle eine andere Zelle enthält, aber ich erhalte einen Fehler in der Zeile Zeilen von "Feld 'Kind' hat unvollständigen Typ". Wie geht's?

typedef struct Cell {
  int isParent;
  Cell child;
} Cell;
119
Ziggy

Es ist klar, dass eine Zelle keine andere Zelle enthalten kann, da sie zu einer nie endenden Rekursion wird.

Eine Zelle KANN jedoch einen Zeiger auf eine andere Zelle enthalten.

typedef struct Cell {
  bool isParent;
  struct Cell* child;
} Cell;
167
Andrew Grant

In C können Sie nicht auf die Typdefinition verweisen, die Sie mit der Struktur selbst erstellen. Sie müssen den Strukturnamen wie im folgenden Testprogramm verwenden:

#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;
}

Obwohl es im Standard wahrscheinlich viel komplizierter ist, können Sie es sich als den Compiler vorstellen, der über struct Cell in der ersten Zeile des typedef, aber bis zur letzten Zeile nichts über tCell zu wissen :-) So erinnere ich mich an diese Regel.

24
paxdiablo

Aus theoretischer Sicht können Sprachen nur selbstreferentielle Strukturen unterstützen, nicht selbstinklusive Strukturen.

15
Sundar

Es gibt eine Art Weg, dies zu umgehen:

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

struct Cell;
typedef struct Cell Cell;

Wenn Sie dies so deklarieren, wird dem Compiler ordnungsgemäß mitgeteilt, dass struct Cell und plain-ol'-cell identisch sind. Sie können Cell also wie gewohnt verwenden. Trotzdem muss struct Cell in der ursprünglichen Deklaration selbst verwendet werden.

12

Ich weiß, dass dieser Beitrag alt ist. Um den gewünschten Effekt zu erzielen, sollten Sie jedoch Folgendes ausprobieren:

#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;

In beiden im obigen Codefragment genannten Fällen MÜSSEN Sie Ihre untergeordnete Zellstruktur als Zeiger deklarieren. Wenn Sie dies nicht tun, erhalten Sie den Fehler "Feld 'Kind' hat unvollständigen Typ". Der Grund dafür ist, dass "struct Cell" definiert werden muss, damit der Compiler weiß, wie viel Speicherplatz bei seiner Verwendung zugewiesen werden muss.

Wenn Sie versuchen, "struct Cell" in der Definition von "struct Cell" zu verwenden, kann der Compiler noch nicht wissen, wie viel Platz "struct Cell" einnehmen soll. Der Compiler weiß jedoch bereits, wie viel Platz ein Zeiger benötigt, und (mit der Forward-Deklaration), dass "Cell" eine Art "struct Cell" ist (obwohl er noch nicht weiß, wie groß eine "struct Cell" ist ). Der Compiler kann also eine "Zelle *" innerhalb der Struktur definieren, die definiert wird.

8
Shawn

Lassen Sie uns die grundlegende Definition von typedef durchgehen. Mit typedef können Sie einen Alias ​​für einen vorhandenen Datentyp definieren, der entweder benutzerdefiniert oder eingebaut ist.

typedef <data_type> <alias>;

beispielsweise

typedef int scores;

scores team1 = 99;

Hier liegt eine Verwechslung mit der selbstreferenzierenden Struktur vor, die auf ein Element desselben Datentyps zurückzuführen ist, das nicht zuvor definiert wurde. So können Sie Ihren Code auf übliche Weise wie folgt schreiben:

//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;

Aber letzte Option: Erhöhen Sie einige zusätzliche Zeilen und Wörter, mit denen wir normalerweise nichts anfangen wollen (wir sind so faul, wie Sie wissen;)). Also lieber View 2.

3
vineetv2821993

Eine andere bequeme Methode besteht darin, die Struktur mit dem Struktur-Tag vorab zu tippen:

//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;
2
Keynes

Eine Struktur, die einen Verweis auf sich selbst enthält. Ein häufiges Vorkommen in einer Struktur, die einen Knoten für eine Linkliste beschreibt. Jeder Knoten benötigt einen Verweis auf den nächsten Knoten in der Kette.

struct node
{
       int data;
       struct node *next; // <-self reference
};
1
DARSHINI DESAI

Alle vorherigen Antworten sind großartig. Ich wollte nur einen Einblick geben, warum eine Struktur keine Instanz eines eigenen Typs enthalten kann (keine Referenz).

es ist sehr wichtig zu beachten, dass Strukturen 'Wert'-Typen sind, dh, sie enthalten den tatsächlichen Wert. Wenn Sie also eine Struktur deklarieren, muss der Compiler entscheiden, wie viel Speicher für eine Instanz davon reserviert werden soll, also durchläuft er alle ihre Mitglieder und fügt hinzu Wenn der Compiler jedoch eine Instanz derselben Struktur gefunden hat, ist dies ein Paradoxon (dh um zu wissen, wie viel Speicherstruktur A benötigt, müssen Sie entscheiden, wie viel Speicher Sie benötigen) Struktur A nimmt!).

Referenztypen unterscheiden sich jedoch, wenn eine Struktur 'A' eine 'Referenz' auf eine Instanz ihres eigenen Typs enthält, obwohl wir noch nicht wissen, wie viel Speicher ihr zugeordnet ist, wissen wir, wie viel Speicher einem Speicher zugeordnet ist Adresse (dh die Referenz).

HTH

1
m.eldehairy