В первом случае ваша структура имеет два эквивалентных имени: struct Element
(где Element
- это тег структуры) и Element
(где Element
- это определение типа, псевдоним существующего типа).
Во втором случае вы просто не определили тег для структуры. Обычно это было бы совершенно правильно, но здесь вы ссылаетесь на несуществующий тип struct Element
в объявлении члена next
.
В этом контексте struct Element
является неполным типом . Вы не можете объявлять объекты неполных типов, но вы можете объявлять указатели на них.
Декларация
typedef struct
{
char value;
struct Element *next;
} Element;
допустимо, но не делает next
указателем на тип вложения. Это делает его указателем на некоторый неполный тип, и вы не сможете ссылаться на него до тех пор, пока вы не объявите полный тип.
Ваше второе заявление является одним из множества вещей, которые не имеют смысла, но все же являются законными C.
Вы могли бы подумать о том, чтобы просто опустить typedef и последовательно ссылаться на тип как struct Element
. Многим нравится удобство иметь однозначное имя для структурного типа, но я лично считаю, что в этом нет особой выгоды (если тип действительно непрозрачный, то есть пользователи типа даже не знаю, что это структура). Это вопрос стиля.
Обратите внимание, что вам нужно ссылаться на тип как struct Element
, а не Element
, внутри самого определения, так как имя typedef Element
пока не видно.
Тот факт, что теги struct и typedef имеют одно и то же имя, может показаться странным, но это совершенно законно. Структурные теги и typedefs находятся в отдельных пространствах имен (в смысле C, а не в C ++); тег struct может появляться только сразу после ключевого слова struct
.
Другой альтернативой является отделение typedef от определения структуры:
typedef struct Element Element;
struct Element {
char value;
Element *next;
};
(Вы можете использовать неполное имя типа в typedef
.)