且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

将指向属于同一类型结构的成员的结构的指针分配给指向同一类型结构的另一个指针

更新时间:2023-11-28 22:55:04

应该写什么

假设问题中的代码是这样写的:

What should be written

Suppose the code in the question were written like this:

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 XY;Y 成为 X 类型的同义词——在你的情况下,Xstruct NodeY 将是节点.)

Then the name Node would be a synonym (alias) for struct Node. (For any typedef X Y;, Y becomes a synonym for type X — where in your case, X would be struct Node and Y would be Node.)

演员阵容:

currentNode = (Node *)currentNode->leftChild;

将是不必要的(但大部分是无害的),因为它是一个空操作——类型 struct Node *Node * 将是同一个指针的两个名称类型.类似的:

would be unnecessary (but mostly harmless) because it would be a no-op — the types struct Node * and Node * would be two names for the same pointer type. Similarly for:

coverNode->leftChild = (struct Node *)newNode;

演员表是不必要的,但(大部分)是无害的.会存在将人与演员混淆的小风险.如果可能的话,***避免强制转换,如果没有强制转换会更好地编写这些:

The cast would be unnecessary but (mostly) harmless. There would be a small risk of confusing people with the cast. It is better to avoid casts when possible, and these would be better written without the casts:

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_structstruct NodeNode.在这种情况下,struct Node_structNode 是同义词,而 struct Node 是一个不完整的结构类型(或者,至少,它是不完整的通过问题中的任何代码).它与 struct Node_structNode 完全无关,除非巧合的是它在结构内部被引用.

Now we have three type names in play: struct Node_struct, struct Node, and Node. In this case, struct Node_struct and Node are synonyms, and struct Node is an incomplete structure type (or, at least, it is not completed by any code in the question). It is wholly unrelated to either struct Node_struct or Node except by the coincidence that it is referenced inside the structure.

使用这种表示法,强制转换是必要的",因为您在指向不相关类型(struct Node *struct Node_struct *)的指针之间进行转换.幸运的是,有规则说所有结构类型指针都是可以相互转换的,并且必须具有相同的大小和对齐要求(C11 §6.2.5 类型¶28§6.3.2.3 指针¶7).

With this notation, the casts are 'necessary' because you're converting between pointers to unrelated types (struct Node * and struct Node_struct *). Fortunately, there are rules that say all structure type pointers are inter-convertible and must have the same size and alignment requirements (C11 §6.2.5 Types ¶28 and §6.3.2.3 Pointers ¶7).

但是您应该删除 Node_struct_struct 部分,以使本答案第一部分的规则适用.在 C 中,使用 (IMO) 是明智的:

But you should drop the _struct part of Node_struct to make the rules of the first part of this answer apply. In C, it is (IMO) sensible to use:

typedef struct SomeTag SomeTag;

以便您随后可以使用 SomeTag * 等.第一个 SomeTag 在标签名称空间中,不会与第二个 SomeTag 冲突>,它在普通标识符命名空间中.参见 C11 §6.2.3 标识符的命名空间.

so that you can subsequently use SomeTag * etc. The first SomeTag is in the tags name space and does not conflict with the second SomeTag, which is in the ordinary identifiers name space. See C11 §6.2.3 Name spaces of identifiers.

另见:

  • Which part of the C standard allows this code to compile?
  • Does the C standard consider that there are one or two struct uperms_entry types in this code?
  • C style/C++ correctness — is struct, union, enum tag same as type name bad in any way?