簡體   English   中英

C-無法從void指針訪問結構元素值

[英]C - Can't access struct element values from void pointer

一些背景:

  • 我是一位長期讀者,但是第一次海報。 我在Java方面經驗不多,但在C語言方面很少。
  • 我創建了一個雙向鏈接列表,其中每個節點中的數據實際上是一個“玩家”結構。
  • 我已經成功填充了列表中每個節點的結構。
  • 我已經對列表本身進行了廣泛的測試,並且表現符合預期。
  • 我希望鏈接列表中的每個節點都具有一個空指針,因為我計划將此代碼用於最終會彼此交互的幾種不同類型的列表。
  • 我的方法是首先將從文件中讀取的值存儲在數組中,然后將這些數據讀取到每個節點的數據元素中。 這似乎已經成功了。

我的問題:當我嘗試訪問“ player”結構中各個元素的值時,我會胡說八道。 我幾乎可以確定這是一個指針問題,因為這是我迄今為止使用C的最大弱點。 相關代碼:

我正在顯示結構,以防萬一我不清楚。 注意Node中的void指針,該指針最終指向Player結構:

struct Node;
typedef struct Node {
    void *data;
    struct Node *prev;
    struct Node *next;
} Node;

typedef struct Player {
    char *name;
    char *pos;
    double *num;
} Player ;

我將包含我編寫的代碼,其中將數組中的數據添加到列表中並打印結果。 我還將顯示結果控制台輸出。

// char *vals[linesInFile][3] has already been declared.
// List playerList has already been created and initialized; it currently has 0 nodes.
// int i represents the number of nodes in the list.
// getNode and addNode do just what you'd expect them to do.  Both functions have been thoroughly tested.`

Player *player = calloc(1, sizeof(Player));
int n;
for(n = 0; n < i; n++) {
    if(vals[n][0] != NULL) {
        addNode(playerList, n, NULL);
        getNode(playerList, n)->data = &player;
        ((Player *)getNode(playerList, n)->data)->name = vals[n][0];
        ((Player *)getNode(playerList, n)->data)->pos = vals[n][1];
        ((Player *)getNode(playerList, n)->data)->num = vals[n][2];
        printf("%d: %s\n", n, ((Player *)getNode(playerList, n)->data)->name);
        printf("%d: %s\n", n, ((Player *)getNode(playerList, n)->data)->pos);
        printf("%d: %s\n", n, ((Player *)getNode(playerList, n)->data)->num);
        printf("\n");
    }
}

0:邁克·特勞特
0:CF
0:4276

1:布萊斯·哈珀
1:低頻
1:4599

2:何塞·費爾南德斯
2:SP
2:5023

到目前為止一切正常。 最后,我包含了我編寫的代碼片段,這些代碼片段試圖從主函數中查找播放器結構的值。

// The getSize method has been tested and correctly returns the size of a list.
int i;
for(i = 0; i < getSize(playerList); i++) {
    printf("%d: %s\n", i, ((Player *)getNode(playerList, i)->data)->name);
    // The output from this is garbage.
    char *playerName = ((Player *)getNode(playerList, i)->data)->name;
    printf("%d: %s\n", i, playerName);
    // The output from this is garbage.
}

我不能肯定最后一塊之前的所有代碼都是正確的,但至少看起來似乎正在產生所需的輸出。 希望這只是最后一塊代碼的簡單指針問題。 無論如何,任何幫助將不勝感激。

這行似乎是錯誤的:

getNode(playerList, n)->data = &player;

player已經是一個指向Player的指針,因此,此行實際上是將新節點的data字段設置為一個指向 Player指針的指針 ,其余的代碼使用它就像是指向Player的指針-類型不匹配,即你的問題。

相反,該行應為:

getNode(playerList, n)->data = player;

也就是說,您無需應用操作員的地址。 其余代碼看起來還不錯。

該代碼似乎很好,因為您的打印語句具有誤導性。 您僅分配一個節點,並不斷更改其值。 事實是,每次更改該節點上的字段時,都將其打印出來,因此輸出看起來正確,但是該程序一次只存儲一個節點,其中包含一條信息。 您存儲,打印,覆蓋,打印,覆蓋,打印...。

要解決此問題,您需要在每次迭代中顯式分配一個新節點:

Player *player;
int n;
for(n = 0; n < i; n++) {
    if(vals[n][0] != NULL) {
        player = calloc(1, sizeof(Player));
        addNode(playerList, n, NULL);
        getNode(playerList, n)->data = player;
        ((Player *)getNode(playerList, n)->data)->name = vals[n][0];
        ((Player *)getNode(playerList, n)->data)->pos = vals[n][1];
        ((Player *)getNode(playerList, n)->data)->num = vals[n][2];
    }
}

然后, 在填充列表之后 ,打印它:

for(n = 0; n < i; n++) {
    if(vals[n][0] != NULL) {
        printf("%d: %s\n", n, ((Player *)getNode(playerList, n)->data)->name);
        printf("%d: %s\n", n, ((Player *)getNode(playerList, n)->data)->pos);
        printf("%d: %s\n", n, ((Player *)getNode(playerList, n)->data)->num);
        printf("\n");
    }
}

另外,如果您不想從數組中復制指針,但要復制其內容,則可以使用strdup()

        /* ... */
        ((Player *)getNode(playerList, n)->data)->name = strdup(vals[n][0]);
        ((Player *)getNode(playerList, n)->data)->pos = strdup(vals[n][1]);

但是,請記住,你現在必須free()中的每一個namepos釋放節點本身之前。 另外,由於num是指向double的指針,因此不能在其上使用strdup 相反,您必須手動分配內存並復制其內容:

        ((Player *)getNode(playerList, n)->data)->num = malloc(sizeof(double));
        *((Player *)getNode(playerList, n)->data)->num = *vals[n][2];

除了FilipeGonçalves指出的&問題,您還有其他一些問題。

您僅分配一個Player結構,然后將其用於列表中的每個項目。 這將意味着它們都指向相同的數據,並且您最終將多次打印最后的播放器詳細信息。 您應該將calloc移至for n循環內。

您還只從val中復制了名稱,pos和num值的指針。 這可能很好,但這確實意味着在玩家列表的生存期內,val必須保持在作用域內(或不被釋放)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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