C имеет четыре различных пространства имен, где пространство имен тега структуры является одним из них. Следовательно:
struct foo { int bar; };
не определяет новый тип в общем смысле. Если у вас есть только тег структуры, вам необходимо добавить ключевое слово struct в объявлениях объектов, например:
foo b; /* error */
struct foo b; /* correct */
Кроме того, вы можете сразу создать новый объект в определении следующим образом:
struct foo { int bar; } baz;
Где baz - это объект типа структуры foo. Тем не менее, часто требуется определить структуру как новый тип, чтобы сохранить некоторые записи. Полный тип не ссылается на теги структуры, поэтому вы можете опустить префикс 'struct' во время объявлений.
typedef struct foo { int bar; } baz;
Тем не менее позволяет вам объявлять объекты с помощью 'struct foo', так как foo является тегом struct. Но теперь он превращается в полный тип в «пространстве имен» нормального типа, где он называется типом baz. Так что с typedef, поля (поля) 'baz' имеют различную семантику.
Если вам не нужно объявлять указатели на тип структуры внутри себя (связанные списки, древовидные структуры), пропустите его. Добавление того, которое не требуется, просто загрязняет пространство имен.