Вам лучше удалить typedefs
, по крайней мере, на начальном этапе, чтобы вы могли лучше понять свои типы.
Вы должны изменить свои структуры, чтобы указывать (а не включать) другие структуры, например:
struct if_expression {
/* struct? */ token *token;
struct expression *condition;
struct block_statement *consequence;
struct block_statement *alternative;
}
Конечно, это приведет к разумному использованию вызовов malloc()
и free()
. В некоторых случаях вы можете позже вернуться к включению (как token
выше, так как не ожидается, что оно указывает на другие ваши структуры, а копирование токенов вокруг - возможно, - дешевая операция).
Для цикличность ссылок, которые вы можете пересылать объявления в C, то есть вы говорите компилятору: «эй, есть структура с именем expression, внутреннюю структуру которой вы еще не знаете, но потерпите меня, вы скоро будете»:
struct expression;
Если позже вы решите использовать typedef
- чтобы ваш код стал более упорядоченным - имейте в виду, что структуры могут иметь имя, а typedefs определяют имена, а эти имена не разделить одно и то же пространство имен. В примерах:
typedef struct {
/* ...internal structure omited... */
} type_a;
typedef struct type_b {
/* ...internal structure omited... */
} type_b;
typedef struct struct_c {
/* ...internal structure omited... */
} type_c;
Здесь type_a
- это тип, определение которого является анонимной структурой. И type_b
- это тип, определение которого struct type_b
, то есть именованная (type_b
) структура. И type_c
- это тип, определение которого struct struct_c
, то есть именованная (struct_c
) структура.
Теперь соберите все вместе, вы можете:
/* forward all your structs */
struct expression;
struct if_expression;
struct block_statement;
/* typedef them all */
typedef struct expression expression;
typedef struct if_expression if_expression;
/* actually define them */
struct expression {
/* ... */
}
В качестве сноски вы можете многое узнать о C языке, понимая разницу между декларацией и определением.