[英]C - Can't access struct element values from void pointer
一些背景:
我的問題:當我嘗試訪問“ 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:42761:布萊斯·哈珀
1:低頻
1:45992:何塞·費爾南德斯
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()
中的每一個name
和pos
釋放節點本身之前。 另外,由於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.