samowiercąca definicja struktury?

Nie pisałem C zbyt długo, więc nie jestem pewien, jak powinienem robić tego rodzaju rekurencyjne rzeczy... Chciałbym, aby każda komórka zawierała inną komórkę, ale pojawia się błąd "pole' dziecko 'ma niekompletny Typ". Co jest?

typedef struct Cell {
  int isParent;
  Cell child;
} Cell;
Author: Community, 2009-02-26

9 answers

Oczywiście komórka nie może zawierać innej komórki, ponieważ staje się niekończącą rekurencją.

Jednak komórka może zawierać wskaźnik do innej komórki.

typedef struct Cell {
  bool isParent;
  struct Cell* child;
} Cell;
 154
Author: Andrew Grant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-26 04:17:55

W C, nie możesz odwoływać się do typedef, który tworzysz w samej strukturze. Musisz użyć nazwy struktury, tak jak w poniższym programie testowym:

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

Chociaż jest to prawdopodobnie o wiele bardziej skomplikowane niż to w standardzie, można myśleć o nim jako o kompilatorze, który wie o struct Cell w pierwszej linii typedef, ale nie wie o tCell aż do ostatniej linii :-) tak pamiętam tę regułę.

 22
Author: paxdiablo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-10 13:13:35

Z teoretycznego punktu widzenia, języki mogą wspierać tylko struktury autotransferowe, a nie struktury autotransferowe.

 13
Author: Sundar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-29 19:13:40

Można to jakoś obejść:

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

struct Cell;
typedef struct Cell Cell;

Jeśli zadeklarujesz to w ten sposób, to poprawnie powie kompilatorowi, że struct Cell i plain-ol'-cell są takie same. Więc możesz używać komórki jak zwykle. Nadal jednak trzeba użyć komórki struct wewnątrz samej deklaracji początkowej.

 12
Author: Benjamin Horstman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-29 19:05:30

Wiem, że ten post jest stary, jednak aby uzyskać efekt, którego szukasz, możesz spróbować:

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

W jednym z dwóch przypadków wymienionych w powyższym fragmencie kodu, musisz zadeklarować swoją strukturę komórki potomnej jako wskaźnik. Jeśli tego nie zrobisz, pojawi się błąd "pole' dziecko 'ma niekompletny Typ". Powodem jest to, że" komórka struct " musi być zdefiniowana, aby kompilator wiedział, ile miejsca przydzielić, gdy jest używana.

Jeśli spróbujesz użyć "struct Cell" wewnątrz definicji "struct Cell", wtedy kompilator nie może jeszcze wiedzieć, ile miejsca ma zająć" struct Cell". Jednak kompilator wie już, ile miejsca zajmuje wskaźnik i (z deklaracją forward) wie, że "komórka" jest typem "komórka struktury" (chociaż nie wie jeszcze, jak duża jest "komórka struktury"). Kompilator może więc zdefiniować "komórkę *" wewnątrz definiowanej struktury.

 7
Author: Shawn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-24 01:54:32

Przejdźmy do podstawowej definicji typedef. typedef użyj do zdefiniowania aliasu do istniejącego typu danych albo jest on zdefiniowany przez użytkownika lub wbudowany.

typedef <data_type> <alias>;

Na przykład

typedef int scores;

scores team1 = 99;

Tutaj jest zamieszanie z samorelacyjną strukturą, ze względu na element tego samego typu danych, który nie jest wcześniej zdefiniowany. Więc w standardowy sposób możesz zapisać swój kod jako: -

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

Ale ostatnia opcja zwiększ kilka dodatkowych linii i słów z zazwyczaj nie chcemy robić (jesteśmy tak leniwi wiesz;)). Więc preferuj widok 2.

 3
Author: vineetv2821993,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-23 10:19:30

Struktura, która zawiera odniesienie do siebie. Często występuje to w strukturze opisującej węzeł dla listy linków. Każdy węzeł wymaga odniesienia do następnego węzła w łańcuchu.

struct node
{
       int data;
       struct node *next; // <-self reference
};
 2
Author: DARSHINI DESAI,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-24 01:51:19

Inną wygodną metodą jest wstępne wpisanie struktury za pomocą znacznika structure jako:

//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
Author: Keynes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-24 18:48:49

Wszystkie poprzednie odpowiedzi są świetne, po prostu pomyślałem, aby dać wgląd w to, dlaczego struktura nie może zawierać instancji własnego typu (nie odniesienia).

Bardzo ważne jest, aby zauważyć, że struktury są typami 'value', tzn. zawierają rzeczywistą wartość, więc kiedy deklarujesz strukturę, kompilator musi zdecydować, ile pamięci przydzielić do jej instancji, więc przechodzi przez wszystkie jej elementy i sumuje ich pamięć, aby dowiedzieć się o całej pamięci struktury, ale jeśli kompilator znaleziono instancję tej samej struktury wewnątrz, to jest to paradoks (tzn. aby wiedzieć, ile zajmuje struct A pamięci, musisz zdecydować, ile zajmuje struct A pamięci !).

Ale typy referencji są różne, jeśli struktura ' a 'Zawiera ' referencję' do instancji własnego typu, chociaż nie wiemy jeszcze, ile pamięci jest do niej przydzielone, wiemy, ile pamięci jest przydzielone do adresu pamięci (tj. referencji).

HTH

 1
Author: m.eldehairy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-11 17:28:27