2016-07-04 10 views
0

Im folgenden Code sehen Sie eine einfache Integer-Linked-Liste, realisiert mit Zeigern in C. Ich habe zwei verschiedene Funktionen zum Einfügen eines neuen int val an der Spitze der Liste. Ich dachte, dass diese 2 Funktionen gleichwertig wären, aber wie die Ausgabe zeigt, sind sie nicht.C: Verkettete Listen - Funktion "Insert first" funktioniert nicht wie erwartet

#include <stdio.h> 
#include <stdlib.h> 

typedef struct _IntlistElem* Intlist; 
typedef struct _IntlistElem {int val; Intlist next;} IntlistElem; 

Intlist insertfirst(int val, Intlist list) { 
    Intlist new = malloc(sizeof(IntlistElem)); 
    new->val = val; 
    new->next = list; 

    return new; 
} 

Intlist insertfirstAlternative(int val, Intlist list) { 
    IntlistElem new = {val, list}; 
    Intlist head = &new; 

    return head; 
} 

void print(Intlist l){ 
    while (l!=NULL){ 
     printf("%d\n", l->val); 
     l = l->next; 
    } 
printf("_____\n"); 
} 

int main(){ 
    Intlist ls = NULL; 
    ls = insertfirst(2, ls); 
    ls = insertfirst(1, ls); 
    print(ls); 

    Intlist lsAlt = NULL; 
    lsAlt = insertfirstAlternative(2, lsAlt); 
    lsAlt = insertfirstAlternative(1, lsAlt); 
    print(lsAlt); 

    return 0; 
} 

Ausgang:

1 
2 
_____ 
1 
1 
... 

Meine Fragen sind:
1. Warum ist die Druckfunktion nicht beendet? (nach Aufruf der Alternativfunktion)
2. Warum sind diese 2 "insertfirst" -Funktionen nicht wie erwartet?
Was ist der Unterschied zwischen diesen Funktionen?

Ich freue mich auf Ihre Antworten. :)

+0

Sie sollten dringend lernen, wie Sie den Debugger verwenden, um Ihren Codefluss und die aktuellen Variablenwerte beim schrittweisen Zeilenumbruch zu überprüfen. –

+1

'Intlist head = &new;': 'neu' ist lokale automatische Variable. Es ist außerhalb des Gültigkeitsbereichs nicht gültig. – BLUEPIXY

+0

Dieser Code kompiliert nicht mit Warnflags (gcc's sind: -Wall -Werror -Wextra). Ich ermutige Sie, sie das nächste Mal zu verwenden. – qleguennec

Antwort

1

Ihre Funktion insertfirstAlternative gibt einen Zeiger auf head zurück. Die Lebensdauer dieser Variablen endet bei der Rückkehr von der Funktion. Daher wird ein ungültiger Zeigerwert zurückgegeben.

Der Wert eines Zeigers wird unbestimmt, wenn das Objekt, auf das er zeigt, das Ende seiner Lebensdauer erreicht.

Alles könnte passieren.

In Ihrem Fall, das zweite Mal, wenn Sie die Funktion aufrufen, wird die zweite head an der gleichen Adresse wie die erste erstellt, so dass der next Zeiger auf das gleiche Objekt zeigt. Daher die Endlosschleife.

+0

Zunächst einmal danke. Aber wie ist es möglich, dass das zugewiesene IntlistElem auch die Variable "new" Punkte am Leben erhält, nachdem "insertfirst" beendet wurde. – CptCook

+0

Es bleibt nicht am Leben. Aus Gründen der Effizienz wird der Speicher nicht gelöscht und das Lesen von seiner Adresse (durch Ihren ungeeigneten Zeiger) funktioniert irgendwie. Aber das ist nur Zufall. Wenn Sie andere Funktionen dazwischen aufrufen, wird der Speicher wahrscheinlich wiederverwendet und überschrieben. –

+0

Okay danke. Das bedeutet also, dass eine verknüpfte Liste nicht "sicher" sein kann? – CptCook