2016-08-29 5 views
-2

Я попытался создать функцию, которая добавит узел в начало списка, а затем изменит переменную «head» (удерживая предыдущее начало списка), чтобы содержать новый узел.Почему не меняется список моих связанных списков?

void addToStart(node * n, node * first){ 
    printf("[Before adding] Node: %d, First: %d\n",&(*n),&(*first)); 
    n->next = first; 
    first = n; 
    printf("[After adding] Node: %d, First: %d\n",&(*n),&(*first)); 
} 


int main(){ 
    node * head = createNode(0); 
    printf("This is the location of head: %d\n",&(*head)); 
    node * fred = createNode(2); 
    addToStart(fred,head); 
    traverse(head); //Displays the list starting from the given node 
    return 0; 
} 

Это выход:

This is the location of head: 10113040                                     
[Before adding] Node: 10113072, First: 10113040                                   
[After adding] Node: 10113072, First: 10113072                                   
(0)[10113040]->NULL 

Проблема заключается в том, что я ожидал, что функция, чтобы изменить то, что head указывал на, но в действительности ничего не изменилось.

+0

'first = n' изменяет параметр функции' first' в 'addToStart', но не' head' из 'main'. 'first' - это копия' head', потому что C имеет значение pass-by-value и изменяется только копия. –

+0

По той же причине, что 'void f (int n) {n = 0; } 'не может использоваться для установки целого числа в ноль. Как и во всех вещах на C, попробуйте сначала понять ситуацию для 'int', а затем обобщить на другие типы. –

+0

Вы правы в ситуации «int», но не указатели, ссылающиеся на переменную, а не на перенос самой переменной? Я предполагал передать переменную указателя, и изменение указателя также эффективно изменило бы исходную переменную. –

ответ

0

Потому что addToStart принимает копия указателя головы как node *. Чтобы изменить голову, вам нужно использовать

void addToStart(node * n, node ** first){ 
          // ^
    printf("[Before adding] Node: %d, First: %d\n",&(*n),&(**first)); 
    n->next = *first; 
      //^
    *first = n; 
//^
    printf("[After adding] Node: %d, First: %d\n",&(*n),&(**first)); 
} 

Edit Каждая функция в C получает свою собственную копию параметров, так что на самом деле нет такой вещи, как ссылки, как в C++ или других языках. Где бы вы ни использовали ссылку, быстрый и грязный вариант (который может не всегда работать!) Заключается в том, чтобы перед каждым упоминанием добавить дополнительный *. Здесь вы хотели бы указать first. first - указатель на узел, так что это уже node *. Чтобы использовать его как «ссылку» (как бы), он получает дополнительный *, следовательно node **. Точно так же, где бы он ни упоминался, он получает дополнительно *: *first = ....

См. a Java answer that's related для получения дополнительной информации о внутренних компонентах Java. В основном, первый * неяв в переменных экземпляра Java. Таким образом, Node n; в Java (вроде), как Node *n; в C.

Надеюсь, что это поможет - обязательно проверьте связанный дублированный вопрос в верхней части страницы и ответы там. Если вы столкнулись с проблемой другого кода, просто задайте другой вопрос!

Примечание для мастеров C: Да, я знаю, что слепо добавить * - плохая идея! Иногда это полезно. Я пытаюсь ответить на комментарий OP таким образом, чтобы переместить OP на один шаг вперед.

+0

Спасибо, я понимаю, что вы сделали ... но я думаю, что это заставило меня понять недоразумение, которое у меня может быть. Я думал, что указатель был аналогичен ссылочной переменной в Java; поэтому, когда я передал аргумент 'node * first' и 'node * n', не сделал бы 'first = n' изменить указатель? –

+0

@AdnanZaman Отредактировано :) – cxw

+0

Теперь это то, чего я не знал! Ничего себе, что делает много ошибок, которые я имел в прошлом, теперь имеет гораздо больше смысла. Эти ошибки больше не кажутся такими мистическими. Полагаю, это то, что они подразумевают под «пропуском». Спасибо огромное! –

Смежные вопросы