应该写什么
假设问题中的代码是这样写的:
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
and Y
将是节点。)
演员阵容:
currentNode = (Node *)currentNode->leftChild;
是不必要的(但大多是无害的),因为这将是一个空操作 - 类型struct Node *
and 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
, and Node
。在这种情况下,struct Node_struct
and Node
是同义词,并且struct Node
是不完整的结构类型(或者至少,它没有由问题中的任何代码完成)。它与任何一个都完全无关struct Node_struct
or Node
除了巧合的是它在结构内部被引用。
使用这种表示法,强制转换是“必要的”,因为您要在指向不相关类型的指针之间进行转换(struct Node *
and struct Node_struct *
)。幸运的是,有一些规则规定所有结构类型指针都是可相互转换的,并且必须具有相同的大小和对齐要求(C11§6.2.5 类型 ¶28 and §6.3.2.3 指针 ¶7).
但你应该放弃_struct
部分Node_struct
使本答案第一部分的规则适用。在 C 中,(IMO)使用以下命令是明智的:
typedef struct SomeTag SomeTag;
以便您随后可以使用SomeTag *
等等第一个SomeTag
位于标签命名空间中并且与第二个不冲突SomeTag
,它位于普通标识符名称空间中。见C11§6.2.3 标识符的命名空间.
也可以看看:
- C 标准的哪一部分允许编译此代码?
- C标准是否认为存在一两个struct uperms_entry在这段代码中输入?
- C 风格/C++ 正确性 — 是struct, union, enum与类型名称相同的标签有什么不好的吗?