C中的类型问题

问题描述:

这可能是一个愚蠢的问题,我看到类似的问题被问到,但我没有得到答案。为什么下面的代码产生: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

使数组为指针数组来修正这个错误,因为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

因为一个是结构,另一个是指针的结构。

create_node()函数返回一个指针一个节点(你真的应该malloc()在功能的方式),并尝试将其分配到阵列中的实际结构。

您可以通过简单地改变你的宣言来解决这个问题:

node_t *list_array[10]; 

,以便它的数组的指针,而不是结构的数组。

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

因为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

这是经典的“指针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

对于这个程序,我没有看到使用动态存储持续时间(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; 
}