![](/img/trans.png)
[英]Can a struct have a member which is a pointer to a struct of the same type?
[英]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
甚至對我來說,這個問題聽起來也很令人困惑,它看起來似乎很明顯或已經回答了,但是我進行了很多搜索,盡管我發現了一些有趣的東西,但並未找到完全適合我問題的答案。 這是一些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;
}
...
}
此代碼正確嗎? 由於currentNode
的類型為Node*
,而currentNode->leftChild
的類型為struct Node*
,因此我必須轉換(Node*)currentNode->leftChild
以便可以將其分配給currentNode
。 但是我不確定這是否正確,必要,或者是否有更好的方法可以做到這一點。
同樣,我也有這個:
Node* coverNode = NULL;
...
coverNode->leftChild = (struct Node*)newNode;
假設問題中的代碼是這樣寫的:
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
類型的同義詞-在您的情況下, 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標識符的命名空間 。
也可以看看:
在c++
,當您說struct Node
, Node
[立即]成為一種類型。 因此,您可以說:
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;
}
}
但是, c
,它僅僅是在“標簽”命名空間, 沒有定義類型。 因此,您想要:
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;
}
}
另外,您可以使用前向聲明 :
// 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;
}
}
需要注意的是, 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;
}
}
為了允許您的兩個結構的交叉鏈接,我們可以這樣做:
// 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.