2016-10-20 3 views
0

Я практикую код связанного списка. Ниже приводится функция вставки для этого:Исходное значение не изменяется при передаче по ссылке?

Node* insert_at_pos(Node *head, int pos){  
    struct Node *ptr=NULL; 
    printf("enter data\n"); 
    ptr=(Node*) malloc(sizeof(Node)); 
    scanf("%d",&ptr->data); 
    ptr->next=NULL; 
    if (pos==0){ 
     if (head==NULL){ 
      head=ptr; 
      return head; //return that I want to remove 
     } 
    } 
    printf("done\n"); 
} 

Вместо возвращения Node*, если я вернусь void, я думаю, что этот код должен еще работать, потому что я передавая значение по ссылке. Поэтому значение head должно обновляться автоматически, а не возвращать его, но оно не работает, если я удалю Node* и положил void в обратном типе insert_at_pos.

И я звоню insert_at_pos функции, как это ::

Node *head=insert_at_pos(head,0); 

Что может быть возможным объяснением или что происходит здесь не так?

+2

Возможный дубликат [Как изменить указатель, который был передан в функцию в C?] (Http://stackoverflow.com/questions/766893/how-do-i-modify-a-pointer -that-has-was-got-into-a-function-in-c) –

+1

Да, это определенно дубликат [Как изменить указатель, который был передан в функцию в C] (http: // stackoverflow .com/questions/766893/how-do-i-modify-a-pointer-that-was-got-got-in-a-function-in-c) –

ответ

2

Существует два способа решения этой проблемы. Либо вы передаете адрес указателя (тип Node**, pass &head), либо вы создадите отдельный тип списка.

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

typedef struct List { 
    Node *head; 
} List; 

новый пустой список, то можно создать так:

List *list = malloc(sizeof (List)); 
list->head = NULL; 

Оба способа хороши. Концептуально второе решение лучше соответствует фактической проблеме, поскольку оно отличает список от узлов данных. Вы можете создать список и добавить или удалить значения без изменения дескриптора списка.

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

Функция вставки с помощью первого раствора может быть объявлен как это:

void insert(Node **head, int value); 

вызов будет выглядеть следующим образом:

Node *head = null; 
insert(&head, 42); 

Или это может быть объявлена ​​как это (как в вашем вопросе):

Node* insert(Node *head, int value); 

и называется так:

Node *head = null; 
head = insert(head, 42); 
+0

Работает. благодаря! но не могли бы вы объяснить, почему код, который я использую, неверен. концептуально? –

+1

@SamarYadav Это не так, это просто еще один способ сделать это.Я добавил объяснение, объясняющее, почему insert/remove действует странно, когда список переходит из пустого в непустое. –