Проблема с указателем в связанном списке

Как и большинство новичков в C, я реализую простой связанный список.

Каждый узел списка определяется так:

typedef struct list_node {
    void * data;
    struct list_node * next;
} list_node_t;

Я сделал тестовую программу для создания и повторения списка. Операции создания и вставки работают корректно. Однако приведенный ниже код вызывает у меня проблемы:

list_node_t * node = NULL;

list_iter_reset(list, node);

if (node == NULL) {
    printf("Node is NULL.\n");
} else {
    printf("Node is not NULL.\n");
}
fflush(stdout);

Функция list_iter_reset() определена ниже. Обратите внимание, что list->head не указывает на NULL, так как ранее я вставлял узлы в список.

void list_iter_reset(list_t list, list_node_t * node)
{
    node = list->head;

    if (node == NULL) {
        printf("Node is NULL.\n");
    } else {
        printf("Node is not NULL.\n");
    }
    fflush(stdout);
}

Результат выполнения этого кода следующий:

Node is not NULL.
Node is NULL.

Поскольку я передаю указатель на узел функции, почему созданный узел в тестовой программе все еще указывает на NULL после вызова этой функции?

Я предполагаю, что простой арифметический аспект указателя здесь прошел мимо моей головы. Я искал вокруг и не мог найти подобную проблему.

Заранее спасибо.


person Saucy Goat    schedule 09.12.2018    source источник
comment
Кажется, вы хотите передать указатель на указатель (list_node_t**) функции, а не указатель. Функция изменяет значение указателя (node), но это никогда не возвращается к вызывающей стороне.   -  person Rotem    schedule 09.12.2018
comment
Я думаю, вам нужно передать указатель узла как ссылку list_node* &node   -  person Greg K.    schedule 09.12.2018
comment
Спасибо за ответ! Это может показаться наивным, но разве указатель на узел не должен быть всем, что мне нужно, чтобы изменить его значение? Поскольку я передаю адрес памяти узла в функцию, зачем мне нужен второй уровень доступа к памяти?   -  person Saucy Goat    schedule 09.12.2018
comment
@GregK Это c. Ссылок нет.   -  person Rotem    schedule 09.12.2018
comment
@Rotem О да, ты абсолютно прав, я забыл. Тогда это двойной указатель :)   -  person Greg K.    schedule 09.12.2018
comment
@SaucyGoat Отличный вопрос! Указатель — это все, что вам нужно, чтобы изменить значение объекта, на который он указывает. Но здесь вы пытаетесь изменить значение самого указателя. Требуется некоторое время, чтобы осознать это, но кажется, что вы на правильном пути. Для сравнения представьте, что вы передаете int функции и ожидаете, что функция изменит этот int. Вам, конечно, придется пройти int*, верно? Это то же самое, за исключением замены int на node*, поэтому вам нужно передать node**.   -  person Rotem    schedule 09.12.2018
comment
Большое спасибо! Не могли бы вы оставить ответ, чтобы я мог отметить этот вопрос как решенный? Я предполагаю, что это может быть весьма полезно для других новичков в C :)   -  person Saucy Goat    schedule 09.12.2018
comment
@SaucyGoat сделано.   -  person Rotem    schedule 09.12.2018


Ответы (1)


Функция изменяет значение указателя, но никогда не возвращается к вызывающей стороне. Кажется, вы хотите передать указатель на указатель (list_node_t**) на функцию, а не обычный указатель.

void list_iter_reset(list_t list, list_node_t** node)
{
    *node = list->head;

    ...
}

Причина этого в том, что хотя указатель — это все, что вам нужно для изменения значения объекта, на который он указывает, здесь вы пытаетесь изменить значение самого указателя. , то есть куда указывает этот указатель.

Для сравнения представьте, что вы передаете int функции и ожидаете, что функция изменит этот int. Вам, конечно, придется пройти int*, верно? Это то же самое, за исключением замены int на node*, поэтому вам нужно передать указатель на этот тип, который в данном случае node**

person Rotem    schedule 09.12.2018
comment
if также следует изменить, чтобы использовать *node. - person jxh; 09.12.2018