Что следует написать
Предположим, код в вопросе был написан так:
typedef struct Node { // Not Node_struct as in the question!
char keyLine[100];
int occurrences;
struct Node* leftChild;
struct Node* rightChild;
struct Node* parent;
} Node;
Тогда имя Node
будет синонимом (псевдонимом) для struct Node
,(Для любого typedef X Y;
, Y
становится синонимом для типа X
- где в вашем случае X
будет struct Node
, а Y
будет Node.)
Приведение в:
currentNode = (Node *)currentNode->leftChild;
было бы ненужным (но в основном безвредным), потому что это был бы запрет на операции - типы struct Node *
и Node *
были бы двумя именами для одного и того же типа указателя.Аналогично для:
coverNode->leftChild = (struct Node *)newNode;
Приведение было бы ненужным, но (в основном) безвредным.Был бы небольшой риск спутать людей с актерами.Лучше избегать приведений, когда это возможно, и их лучше писать без приведений:
currentNode = currentNode->leftChild;
coverNode->leftChild = newNode;
Что написано
typedef struct Node_struct {
char keyLine[100];
int occurrences;
struct Node* leftChild;
struct Node* rightChild;
struct Node* parent;
} Node;
Теперь у нас в игре три типа имен: struct Node_struct
, struct Node
и Node
.В этом случае struct Node_struct
и Node
являются синонимами, а struct Node
- это неполный тип структуры (или, по крайней мере, он не дополнен каким-либо кодом в вопросе).Он совершенно не связан ни с struct Node_struct
, ни с Node
, за исключением совпадения того, что на него ссылаются внутри структуры.
В этой записи обозначения «необходимы», потому что вы конвертируете между указателями в не связанныетипы (struct Node *
и struct Node_struct *
).К счастью, существуют правила, которые говорят, что все указатели типов структур взаимно конвертируемы и должны иметь одинаковые требования к размеру и выравниванию (C11 §6.2.5 Типы ¶28 и §6.3.2.3 Указатели ¶7).
Но вы должны отбросить _struct
часть Node_struct
, чтобы применить правила первой части этого ответа.В C (IMO) целесообразно использовать:
typedef struct SomeTag SomeTag;
, чтобы впоследствии можно было использовать SomeTag *
и т. Д. Первый SomeTag
находится в пространстве имен тегов и не конфликтует со вторымSomeTag
, который находится в пространстве имен обычных идентификаторов.См. C11 §6.2.3 Пространства имен идентификаторов .
См. Также: