通用链表库中的列表创建功能出现问题

时间:2019-04-21 06:58:16

标签: c

我发现了一个通用的链表库,我认为这很有用。但是llist_create(void * new_data)函数使我感到困惑。指针new_list被分配两次。我看到的是,第一个malloc返回的地址将被第二个malloc覆盖。那么为什么要使用第一个malloc? (代码效果很好)

由于我好奇,我尝试通过注释第一个malloc来运行。然后,gcc发出警告“从不兼容的指针类型初始化”。运行代码会导致分段错误。

struct node {
    void *data;
    struct node *next;
};

typedef struct node * llist;   


llist *llist_create(void *new_data)
{
    struct node *new_node;

    //First alloc
    llist *new_list = (llist *)malloc(sizeof (llist));
    //Second alloc
    *new_list = (struct node *)malloc(sizeof (struct node));

    new_node = *new_list;
    new_node->data = new_data;
    new_node->next = NULL;
    return new_list;
}

 //Code which creates linked list in driver program
 llist *my_list = llist_create(NULL);

2 个答案:

答案 0 :(得分:0)

好像您不熟悉c中的typedef

  

typedef是C和C ++编程语言中的保留关键字。它用于为另一种数据类型创建别名。1因此,它通常用于简化声明由struct和Union类型组成的复杂数据结构的语法,但在为整数提供特定的描述性类型名称时一样常见。长度不同的数据类型。

现在看一下这句话:

typedef struct node * llist;   

这意味着lliststruct node *类型的别名。

在此声明中

llist *new_list = (llist *)malloc(sizeof (llist));

new_list的类型为llist *,除了struct node **之外什么都没有。

因此,对new_list的第一个内存分配是指向指向struct node的指针的指针,而第二个分配是对指向struct node的指针。


IMO,OP发布的代码令人困惑,原因有两个:
-typedef指向结构的指针
-创建列表和在列表中添加节点这两个操作组合在一个函数中。

更具可读性的代码如下:

struct node {
    void *data;
    struct node *next;
};

typedef struct node NODE;

struct llist {
    NODE *head;
};

typedef struct llist LLIST;

LLIST *create_list() {
    LLIST *llist = malloc(sizeof(LLIST));
    if (llist == NULL)
        exit(EXIT_FAILURE);

    llist->head = NULL;
    return llist;
}

NODE *create_ll_node(void *data) {
    NODE *node = malloc(sizeof(NODE));
    if (node == NULL)
        exit(EXIT_FAILURE);

    node->data = data;
    node->next = NULL;
    return node;
}

// The add function for inserting node at the start of list
// Parameter: pointer to LLIST
//            data to be insert in node
void add_list_head(LLIST *llist, void *data) {
    NODE *node = create_ll_node(data);
    if (llist->head != NULL) {
        node->next = llist->head;
    }
    llist->head = node;
}

//driver function
int main() {
    LLIST *llist = create_list();
    .....
    .....

    add_list_head(llist, <data>);
    add_list_head(llist, <data>);
    .....
    .....

答案 1 :(得分:0)

llist *llist_create(void *new_data)

正在执行2个操作,它是创建一个新的列表头,并创建一个节点,并为该头提供数据引用。

llist *new_list = (llist *)malloc(sizeof (llist));

首先通过声明类型为llist *的新变量并使用malloc为该指针创建内存来创建列表头。

//Second alloc
*new_list = (struct node *)malloc(sizeof (struct node));

创建一个新的node来保存提供的数据。 两种C*new_list语法中令人困惑,意思不同。

llist *new_list; /* create a variable of pointer to llist */

和      new_list = val; / 写入new_list指向val * /

该函数的其余部分用node填充new_data