Возникла проблема с функцией создания списка в общей библиотеке связанных списков - PullRequest
0 голосов
/ 21 апреля 2019

Я нашел общую библиотеку связанных списков, которая, на мой взгляд, была бы полезна. Но функция 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 голосов
/ 21 апреля 2019
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

0 голосов
/ 21 апреля 2019

Похоже, вы не знакомы с typedef в c.

typedef - зарезервированное ключевое слово в языках программирования C и C ++. Он используется для создания псевдонима для другого типа данных. Как таковой, он часто используется для упрощения синтаксиса объявления сложных структур данных, состоящих из типов struct и union, но столь же распространен в предоставлении конкретных описательных имен типов для целых чисел. типы данных различной длины.

Теперь посмотрите на это утверждение:

typedef struct node * llist;   

Это означает, что llist является псевдонимом для типа struct node *.

В этом утверждении

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

тип new_list равен llist *, что является ничем иным, как struct node **.

Итак, первое выделение памяти для new_list предназначено для указателя на указатель на struct node, а второе выделение для для указателя на struct node.


IMO, код, опубликованный OP, сбивает с толку по двум причинам:
- введите указатель на структуру
- Две операции создания списка и добавления узла в этот список объединены в одну функцию.

Более читаемый код будет выглядеть примерно так:

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>);
    .....
    .....
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...