Я не писал C очень долго, и поэтому я не уверен, как мне следует делать подобные рекурсивные вещи ... Я хотел бы, чтобы каждая ячейка содержала другую ячейку, но я получаю сообщение об ошибке строки "поля 'child' имеют неполный тип". Что происходит?
typedef struct Cell {
int isParent;
Cell child;
} Cell;
Ответы:
Ясно, что ячейка не может содержать другую ячейку, поскольку она становится бесконечной рекурсией.
Однако ячейка МОЖЕТ содержать указатель на другую ячейку.
источник
Cell
пока не входит в сферу применения.Cell*
наcell->child
.struct
s в C в основном просто хранят все свои значения рядом друг с другом, фактически невозможно хранить структуру внутри себя (потому что эта структура должна содержать еще одну и т. Д., Что приводит к структуре памяти бесконечного размера) ,struct Cell
см. Этот ответ .В C вы не можете ссылаться на typedef, который вы создаете, внутри самой структуры. Вы должны использовать имя структуры, как в следующей тестовой программе:
Хотя это, вероятно, намного сложнее, чем это в стандарте, вы можете думать об этом как о компиляторе, который знает о
struct Cell
первой строке,typedef
но не знает о немtCell
до последней строки :-) Вот как я помню это правило.источник
С теоретической точки зрения, Языки могут поддерживать только самоссылочные структуры, но не самодостаточные структуры.
источник
Есть способ обойти это:
Если вы объявите это так, это правильно сообщит компилятору, что struct Cell и plain-ol'-cell одинаковы. Таким образом, вы можете использовать Cell, как обычно. Тем не менее, все же придется использовать struct Cell внутри самого исходного объявления.
источник
struct Cell;
снова написал ?struct Cell
.struct Cell;
излишним. Если, однако, по какой-то причине вы поместили последние две строки в заголовочный файл, который вы включили до того, как определилиCell
структуру с первыми четырьмя строками, то дополнительнаяstruct Cell;
- nececairy.typedef struct Cell Cell;
и он создастCell
псевдоним дляstruct Cell
. Неважно, видел ли компиляторstruct Cell { .... }
раньше.Я знаю, что этот пост старый, но чтобы получить эффект, который вы ищете, вы можете попробовать следующее:
В любом из двух случаев, упомянутых во фрагменте кода выше, вы ДОЛЖНЫ объявить свою дочернюю структуру Cell как указатель. Если вы этого не сделаете, вы получите сообщение об ошибке «поле 'child' имеет неполный тип" ». Причина в том, что "struct Cell" должна быть определена для того, чтобы компилятор знал, сколько места выделяется при его использовании.
Если вы попытаетесь использовать "struct Cell" внутри определения "struct Cell", то компилятор еще не может знать, сколько места должно занимать "struct Cell". Однако компилятор уже знает, сколько места занимает указатель, и (с предварительным объявлением) он знает, что «Cell» является типом «struct Cell» (хотя он еще не знает, насколько велик «struct Cell»). ). Таким образом, компилятор может определить «Cell *» в структуре, которая определяется.
источник
Давайте пройдемся по базовому определению typedef. typedef используется для определения псевдонима для существующего типа данных, определенного пользователем или встроенным.
например
В данном случае путаница связана со структурой со ссылками на себя из-за элемента с тем же типом данных, который не был определен ранее. Таким образом, стандартным способом вы можете написать свой код как: -
Но последний вариант увеличивает лишние строки и слова, обычно мы этого не хотим (мы так ленивы, вы знаете;)). Так что предпочитаю View 2.
источник
typedef
синтаксиса неверно (например, рассмотримtypedef int (*foo)(void);
). Примеры View 1 и View 2 не работают: они имеютstruct Cell
неполный тип, поэтому вы не можете использовать ихchild
в своем коде.Другой удобный метод - предварительно определить структуру с помощью тега структуры как:
источник
Структура, которая содержит ссылку на себя. Это часто встречается в структуре, которая описывает узел для списка ссылок. Каждому узлу нужна ссылка на следующий узел в цепочке.
источник
Все предыдущие ответы хороши, я просто подумал, почему структура не может содержать экземпляр своего типа (не ссылку).
очень важно отметить, что структуры являются типами «значений», то есть они содержат фактическое значение, поэтому, когда вы объявляете структуру, компилятор должен решить, сколько памяти выделить его экземпляру, чтобы он прошел через все его члены и добавил их память, чтобы выяснить всю память структуры, но если компилятор обнаружил экземпляр той же структуры внутри, то это парадокс (то есть, чтобы узнать, сколько занимает структура памяти A, вы должны решить, сколько памяти структура А занимает!).
Но ссылочные типы различны, если структура «A» содержит «ссылку» на экземпляр своего собственного типа, хотя мы еще не знаем, сколько памяти выделено для него, мы знаем, сколько памяти выделено для памяти адрес (т.е. ссылка).
НТН
источник