selbstreferenzielle Strukturdefinition?

Lesezeit: 6 Minuten

Benutzeravatar von Ziggy
Ziggy

Ich habe C noch nicht lange geschrieben und bin mir daher nicht sicher, wie ich diese Art von rekursiven Dingen anstellen soll … Ich möchte, dass jede Zelle eine andere Zelle enthält, aber ich erhalte einen Fehler entlang der Zeilen von “Feld ‘Kind’ hat unvollständigen Typ”. Was ist los?

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

  • PS Eigentlich gibt es “struct Cell” zu “Cell” (das ist ein gängiges Muster)

    – David Z

    26. Februar 2009 um 1:10 Uhr

  • er verwendet wahrscheinlich einen C++-Compiler. er sollte auch _Bool verwenden, wenn es wirklich C ist.

    – Nabi

    26. Februar 2009 um 1:52 Uhr

  • Er sollte int verwenden, wenn es wirklich C ist 🙂

    – paxdiablo

    26. Februar 2009 um 2:04 Uhr

  • Wieso den? C99 hat bool – Sie müssen nur einfügen

    – Jonathan Leffler

    26. Februar 2009 um 4:21 Uhr

  • mögliches Duplikat von C: Zeiger auf Struct in der Struct-Definition

    – Jonathan Leffler

    24. Mai 2014 um 6:51 Uhr

Benutzeravatar von Andrew Grant
Andreas Grant

Eindeutig A Cell kann kein anderes enthalten Cell da es zu einer nie endenden Rekursion wird.

Jedoch ein Cell KANN einen Zeiger auf einen anderen enthalten Cell.

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

  • @cs01 Nein, Cell ist noch nicht im Geltungsbereich.

    – fredoverflow

    30. Dezember 2015 um 13:28 Uhr

  • Es möchten Sinn ergeben. Python erlaubt es und erlaubt sogar die Serialisierung eines solchen Objekts. Warum nicht C++?

    – noɥʇʎʀʎzɐɹƆ

    6. Juni 2016 um 1:06 Uhr

  • Ich erhalte Warnungen, wenn ich versuche, etwas zuzuweisen Cell* zu cell->child.

    – Tomáš Zato

    26. November 2016 um 23:02 Uhr

  • @noɥʇʎʀʎzɐɹƆ Weil Python Zeiger abstrahiert, damit Sie sie nicht bemerken. Seit structs in C im Grunde nur alle ihre Werte nebeneinander speichern, wäre es unmöglich, eine Struktur tatsächlich in sich selbst zu speichern (da diese Struktur eine andere enthalten müsste und so weiter, was zu einer Speicherstruktur unendlicher Größe führen würde).

    – jazzpi

    3. Februar 2017 um 15:31 Uhr

  • Zur Erläuterung der Verwendung von struct Cellsiehe diese Antwort.

    – wizzwizz4

    27. Mai 2017 um 13:53 Uhr

Benutzeravatar von paxdiablo
paxdiablo

In C können Sie nicht auf die Typedef verweisen, die Sie innerhalb 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 sich vorstellen, dass der Compiler davon weiß struct Cell in der ersten Zeile der typedef aber nichts davon wissen tCell bis zur letzten Zeile 🙂 So habe ich diese Regel in Erinnerung.

  • Was ist mit C ++? Können Sie bitte die Antworten zu C ++ verlinken?

    – Rimalroshan

    10. Mai 2018 um 13:09 Uhr

  • @rimiro, die Frage war eine C-Frage. Wenn Sie die Antwort für eine C++-Variante wollen, sollten Sie das tun Fragen es als Frage.

    – paxdiablo

    10. Mai 2018 um 13:12 Uhr

Aus theoretischer Sicht können Sprachen nur selbstreferenzielle Strukturen unterstützen, keine selbsteinschließenden Strukturen.

  • Wie groß wäre aus praktischer Sicht eine solche Instanz von ‘struct Cell’ tatsächlich?

    – Marsh Ray

    29. Juli 2009 um 19:23 Uhr

  • Auf den meisten Maschinen vier Bytes größer als er selbst.

    – TonyK

    23. September 2010 um 20:28 Uhr

Es gibt einen Weg, dies zu umgehen:

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

struct Cell;
typedef struct Cell Cell;

Wenn Sie es so deklarieren, teilt es dem Compiler richtig mit, dass struct Cell und plain-ol’-cell identisch sind. Sie können Cell also ganz normal verwenden. Trotzdem muss struct Cell innerhalb der anfänglichen Deklaration selbst verwendet werden.

Shawns Benutzeravatar
Shawn

Ich weiß, dass dieser Beitrag alt ist, aber um den gewünschten Effekt zu erzielen, sollten Sie Folgendes versuchen:

#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 Fällen, die im obigen Codefragment erwähnt werden, 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 er zuordnen muss, wenn er verwendet wird.

Wenn Sie versuchen, “struct Cell” innerhalb 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 er weiß (mit der Vorwärtsdeklaration), 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 zu definierenden Struktur definieren.

Benutzeravatar von Neuron
Neuron

Eine weitere praktische Methode ist die Vorabtypisierung der Struktur mit dem Struktur-Tag als:

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

Benutzeravatar von vineetv2821993
vineetv2821993

Lassen Sie uns die grundlegende Definition von typedef durchgehen. typedef wird verwendet, um einen Alias ​​für einen vorhandenen Datentyp zu definieren, der entweder benutzerdefiniert oder integriert ist.

typedef <data_type> <alias>;

zum Beispiel

typedef int scores;

scores team1 = 99;

Die Verwirrung liegt hier bei der selbstreferenziellen Struktur aufgrund eines Mitglieds desselben Datentyps, das nicht früher definiert wurde. So können Sie Ihren Code standardmäßig 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 die letzte Option erhöht einige zusätzliche Zeilen und Wörter, die wir normalerweise nicht tun möchten (wir sind so faul, weißt du 😉 ). Also lieber Ansicht 2.

  • Ihre Erklärung der typedef Syntax ist falsch (betrachten Sie z typedef int (*foo)(void);). Ihre Beispiele für Ansicht 1 und Ansicht 2 funktionieren nicht: Sie machen struct Cell ein unvollständiger Typ, sodass Sie ihn nicht verwenden können child in deinem Code.

    – Melpomen

    28. Februar 2018 um 1:38 Uhr

1424220cookie-checkselbstreferenzielle Strukturdefinition?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy