[英]Assign a pointer to a struct that is a member of a struct of the same type to another pointer to a struct of the same type
This question sounds super confusing even for me, and it may seem obvious or already answered, but I have searched a lot and although I found interesting things, I didn't find an answer exactly for my question. 甚至对我来说,这个问题听起来也很令人困惑,它看起来似乎很明显或已经回答了,但是我进行了很多搜索,尽管我发现了一些有趣的东西,但并未找到完全适合我问题的答案。 Here is some C code that will show much better my doubt:
这是一些C代码,这些代码将更好地显示我的疑问:
typedef struct Node_struct {
char keyLine[100];
int occurrences;
struct Node* leftChild;
struct Node* rightChild;
struct Node* parent;
} Node;
typedef struct Tree_struct {
Node* root;
} Tree;
int insertNode(Tree* myTree, Node* newNode) {
...
Node* currentNode = myTree->root;
...
if (caseSenCmpString(newNode->keyLine, currentNode->keyLine) == -1) {
currentNode = (Node*)currentNode->leftChild;
}
...
}
Is this code correct? 此代码正确吗? Since
currentNode
is of type Node*
, and currentNode->leftChild
is of type struct Node*
, I had to cast (Node*)currentNode->leftChild
so that it could be assigned to currentNode
. 由于
currentNode
的类型为Node*
,而currentNode->leftChild
的类型为struct Node*
,因此我必须转换(Node*)currentNode->leftChild
以便可以将其分配给currentNode
。 But I am not sure if this is correct, necessary, or if there is a better way to do the same. 但是我不确定这是否正确,必要,或者是否有更好的方法可以做到这一点。
Similarly, I also have this: 同样,我也有这个:
Node* coverNode = NULL;
...
coverNode->leftChild = (struct Node*)newNode;
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;
Then the name Node
would be a synonym (alias) for struct Node
. 然后,名称
Node
将成为struct Node
的同义词(别名)。 (For any typedef XY;
, Y
becomes a synonym for type X
— where in your case, X
would be struct Node
and Y
would be Node.) (对于任何
typedef XY;
, Y
成为X
类型的同义词-在您的情况下, X
将为struct Node
, Y
将为Node。)
The cast in: 演员表:
currentNode = (Node *)currentNode->leftChild;
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. 它将是不必要的(但大多数情况下是无害的),因为它将是无操作的
struct Node *
和Node *
类型将是同一指针类型的两个名称。 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;
Now we have three type names in play: struct Node_struct
, struct Node
, and Node
. 现在我们可以使用三个类型名称:
struct Node_struct
, struct Node
和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). 在这种情况下,
struct Node_struct
和Node
是同义词,而struct Node
是不完整的结构类型(或者,至少,问题中的任何代码都未完成)。 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
完全无关,除了巧合的是,它在结构内部被引用。
With this notation, the casts are 'necessary' because you're converting between pointers to unrelated types ( struct Node *
and struct Node_struct *
). 使用这种表示法时,强制转换是“必需的”,因为您要在指向不相关类型(
struct Node *
和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 ). 幸运的是,有规则说所有结构类型指针都是可相互转换的,并且必须具有相同的大小和对齐要求( C11§6.2.5类型¶28和§6.3.2.3指针¶7 )。
But you should drop the _struct
part of Node_struct
to make the rules of the first part of this answer apply. 但是,你应该放下
_struct
的一部分Node_struct
使这个答案的第一部分的规则。 In C, it is (IMO) sensible to use: 在C语言中,使用(IMO)明智:
typedef struct SomeTag SomeTag;
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. 这样您便可以随后使用
SomeTag *
等。第一个SomeTag
位于标签名称空间中,并且与第二个SomeTag
冲突,后者位于普通标识符名称空间中。 See C11 §6.2.3 Name spaces of identifiers . 参见C11§6.2.3标识符的命名空间 。
See also: 也可以看看:
struct uperms_entry
types in this code? struct uperms_entry
类型? struct
, union
, enum
tag same as type name bad in any way? struct
, union
, enum
标签与类型名称是否相同? In c++
, when you say struct Node
, Node
[immediately] becomes a type. 在
c++
,当您说struct Node
, Node
[立即]成为一种类型。 So, you could say: 因此,您可以说:
struct Node {
char keyLine[100];
int occurrences;
Node *leftChild;
Node *rightChild;
Node *parent;
};
struct Tree {
Node *root;
};
int
insertNode(Tree *myTree, Node *newNode)
{
Node *currentNode = myTree->root;
if (caseSenCmpString(newNode->keyLine, currentNode->keyLine) == -1) {
currentNode = currentNode->leftChild;
}
}
But, in c
, it is merely in the "tag" namespace and does not define a type. 但是,
c
,它仅仅是在“标签”命名空间, 没有定义类型。 Thus, you want: 因此,您想要:
typedef struct Node {
char keyLine[100];
int occurrences;
struct Node *leftChild;
struct Node *rightChild;
struct Node *parent;
} Node;
typedef struct Tree_struct {
Node *root;
} Tree;
int
insertNode(Tree *myTree, Node *newNode)
{
Node *currentNode = myTree->root;
if (caseSenCmpString(newNode->keyLine, currentNode->keyLine) == -1) {
currentNode = currentNode->leftChild;
}
}
As an alternative, you can use a forward declaration : 另外,您可以使用前向声明 :
// forward declaration
struct Node;
typedef struct Node Node;
struct Node {
char keyLine[100];
int occurrences;
Node *leftChild;
Node *rightChild;
Node *parent;
};
typedef struct Tree_struct {
Node *root;
} Tree;
int
insertNode(Tree *myTree, Node *newNode)
{
Node *currentNode = myTree->root;
if (caseSenCmpString(newNode->keyLine, currentNode->keyLine) == -1) {
currentNode = currentNode->leftChild;
}
}
Note that the struct
name does not have to match the type name: 需要注意的是,
struct
的名字不必匹配类型名称:
// forward declaration
struct Node_struct;
typedef struct Node_struct Node;
struct Node_struct {
char keyLine[100];
int occurrences;
Node *leftChild;
Node *rightChild;
Node *parent;
};
typedef struct Tree_struct {
Node *root;
} Tree;
int
insertNode(Tree *myTree, Node *newNode)
{
Node *currentNode = myTree->root;
if (caseSenCmpString(newNode->keyLine, currentNode->keyLine) == -1) {
currentNode = currentNode->leftChild;
}
}
To allow cross linking of your two structs, we could do: 为了允许您的两个结构的交叉链接,我们可以这样做:
// forward declaration
struct Node_struct;
typedef struct Node_struct Node;
struct Tree_struct;
typedef struct Tree_struct Tree;
struct Node_struct {
char keyLine[100];
int occurrences;
Node *leftChild;
Node *rightChild;
Node *parent;
Tree *tree;
};
struct Tree_struct {
Node *root;
};
int
insertNode(Tree *myTree, Node *newNode)
{
Node *currentNode = myTree->root;
if (caseSenCmpString(newNode->keyLine, currentNode->keyLine) == -1) {
currentNode = currentNode->leftChild;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.