簡體   English   中英

將指向相同類型的結構成員的結構的指針分配給指向相同類型的結構的另一個指針

[英]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 NodeY將為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_structstruct NodeNode 在這種情況下, struct Node_structNode是同義詞,而struct Node是不完整的結構類型(或者,至少,問題中的任何代碼都未完成)。 它與struct Node_structNode完全無關,除了巧合的是,它在結構內部被引用。

使用這種表示法時,強制轉換是“必需的”,因為您要在指向不相關類型( 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 NodeNode [立即]成為一種類型。 因此,您可以說:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM