2013-02-11 75 views
-1

這可能是一個愚蠢的問題,我看到類似的問題被問到,但我沒有得到答案。爲什麼下面的代碼產生:C中的類型問題

error: incompatible types when assigning to type ‘node_t’ from type ‘struct node_t *’

node_t list_array[10]; 
typedef struct node 
{ 
    int value; 
    struct node *next; 
    struct node *prev; 
} node_t; 

node_t* create_node(void) 
{ 
    node_t *np; 
    np->next = NULL; 
    np->prev = NULL; 
    np->value = rand() % 10; 
    return np; 
} 

int main(void) 
{ 
int i; 
for(i = 0; i < 10; i++) 
{ 
    list_array[i] = create_node(); 
} 
return 0; 
}  
+0

爲什麼你有擁有10個'node_t'對象的全局數組,當你顯然要在實現雙向鏈表時動態創建節點?不會是指向'root'節點的簡單指針嗎? – LihO 2013-02-11 10:55:45

+0

@LihO,也許德克斯特想要十個不同的鏈表:-) – paxdiablo 2013-02-11 10:57:02

+0

@paxdiablo:那麼,這也可以解釋名字'list_array'。 :)但我不認爲他想創建10個鏈接列表並使用此數組來存儲10個根節點。 – LihO 2013-02-11 10:59:20

回答

4

使數組爲指針數組來修正這個錯誤,因爲create_node返回一個指針:

node_t *list_array[10]; 

注意你沒有分配任何內存在create_node所以使用np是非法的。嘗試:

node_t *np = malloc(sizeof *np); 

I want to make an array of node_t structs

在這種情況下,你可以離開node_t list_array [10]:

  • &list_array[i]作爲參數傳遞給函數
  • 具備的功能返回node_t代替的一個node_t *
+0

我想創建一個node_t結構數組。如果我理解正確。數組聲明將會保留/定義一個內存空間(因此不使用malloc)。指向next和previous的指針將指向數組中的內存空間,但同時會提供一個替代結構/迭代數組的方式。 – stian 2013-02-11 11:09:13

4

因爲一個是結構,另一個是指針的結構。

create_node()函數返回一個指針一個節點(你真的應該malloc()在功能的方式),並嘗試將其分配到陣列中的實際結構。

您可以通過簡單地改變你的宣言來解決這個問題:

node_t *list_array[10]; 

,以便它的數組的指針,而不是結構的數組。

0

node_t list_array[10]應該node_t *list_array[10] 你也沒有malloc編你的node_t *np

node_t *np = malloc(sizeof(node_t));

+0

我認爲從中得到很多幫助。我不得不說傑里米的解釋非常好。我也相信有人建議將每個數組位置的內存地址賦給一個帶有指針參數的函數。這個指針可以讓我操作原始數組。 – stian 2013-02-11 13:12:07

4

因爲create_node()返回一個指針,但list_array[i]是一個實際實例。你不能爲實例指定一個指針,它們完全不同。

的溶液一般是表示每個節點的指針,這就要求list_array是一個指針數組:

node_t *list_array[10]; 

然後分配新建分配FY是有意義的,並且代碼將編譯。

但是,請注意,代碼不會「工作」,因爲它在create_node()內取指NULL指針。看起來你忘了撥打malloc()

node_t* create_node(void) 
{ 
    node_t *np; 
    if((np = malloc(sizeof *np)) != NULL) 
    { 
     np->next = NULL; 
     np->prev = NULL; 
     np->value = rand() % 10; 
    } 
    return np; 
} 
+0

'node_t * np;'np的值是不確定的,在這裏。你怎麼能確定一個不確定的值是一個空指針?沒有像NULL指針這樣的事情,因爲NULL不是左值。不要將「空指針」一詞與NULL表示的值混淆,這恰好只是空指針集合中的一個成員。 – Sebivor 2013-02-11 13:39:23

1

這是經典的「指針vs.實例」混淆。比你的警告更嚴重的是:

node_t *np; 
np->next = NULL; 

這將編譯,然後段錯誤。

由於誤解了指針是什麼造成了混淆。編譯時,指針只是一個單一的數字,如140734799803888.使用這個數字只是爲了找到物理數據塊。這是一個內存地址

指針與實例混淆,是您在編程中遇到的第一個概念性挑戰之一。所以這裏有一個比喻:

如果你曾經使用過GPS,它會告訴你哪裏是(指針),但不你是什麼(數據)。指針以相同的方式工作。如果有人想握手,他們不會晃動GPS座標(指針)!他們會使用GPS座標來定位你,然後實際訪問你(數據)並握握你的手。這就是指針的工作原理。

所以在上面的代碼中,你聲明瞭一個指針np,但是不要給它任何位置來跟蹤。然後,您問「使用np中的號碼來查找我的數據」(但您沒有爲np設置一個號碼!)特別是,np->next要求使用位置np + someOffset(這是未定義的!)來查找您的物理數據(這是無處),並改變它。

這就是爲什麼你會遇到seg故障。

+0

謝謝你,傑里米。我有興趣更深入地理解指針。對不起,繼續詢問,但我現在刪除了指向NULL的下一個指針的聲明。但是,我保留了np-> value的賦值。我仍然得到相同的錯誤,但是我所掙扎的(以及你告訴我的)是通過說node_t * np我已經聲明瞭一個應該指向node_t的內存位置...但是並沒有實際創建一?我將如何創建指針將指向(不使用malloc)? – stian 2013-02-11 12:59:44

+0

如果你想避開內存分配,你可以直接返回一個node_t。用「node_t」代替每個「node_t *」都可以。不是傳遞位置(又稱指針),而是傳遞結構的整個內容。這對鏈表沒有意義,但是如果你不能使用malloc(),這是可能的。 – 2013-02-11 13:35:19

+0

對不起,我還應該說你的node_t結構聲明不會改變;你仍然可以像「struct node * next」一樣使用指針,這樣你就可以使用它們來「引用」(又稱定位)「下一個」的實際數據。 – 2013-02-11 13:42:36

0

對於這個程序,我沒有看到使用動態存儲持續時間(malloc)。如果您希望將所有對象保留在靜態存儲期內,我會棄用create_node來支持memcpy。例如,

#include <string.h> 

typedef struct node 
{ 
    int value; 
    struct node *next; 
    struct node *prev; 
} node_t; 

int main(void) { 
    node_t list_array[10]; 
    for (int i = 0; i < sizeof (list_array)/sizeof (*list_array); i++) { 
     memcpy(list_array + i, 
       &(node_t){ .value = rand() % 10, 
          .next = NULL, 
          .prev = NULL }, 
       sizeof (*list_array)); 
    } 
    return 0; 
}