Mysteriöse Funktionsweise einer Funktion



  • Hallo Community,

    hab mal wieder ein Problem 🙂
    Folgende Funkition

    int einfuegen(struct binaer_baum *baum, unsigned int p, char *o){
       struct binaer_knoten *knoten, **neu;
    
       neu =(struct binaer_knoten **) &baum->root;
       knoten= (struct binaer_knoten *) baum->root;
       for(;;) {
          if(knoten == NULL) {
             /* Haben wir einen freien Platz gefunden? */
             knoten = *neu =malloc(sizeof *knoten);
             if(knoten != NULL) {
                /* Daten einfuegen */
                knoten->plz = p;
                strcpy(knoten->ort, o);
                knoten->links=knoten->rechts=NULL;
                baum->counter++;
                /* Beendet die Funktion erfolgreich. */
                return 1;
             }
             else {
                fprintf(stderr, "Speicherplatzmangel\n");
                return 0;
             }
          }
          /* Ist die aktuelle Postleitzahl größer? */
          else if(p > knoten->plz)  {
             /* Dann gehts rechts weiter im Baum. */
             neu = &knoten->rechts;
             knoten = knoten->rechts;
          }
          else { /* Der letzte Fall, die aktuelle PLZ ist kleiner, */
             /* dann eben nach links weiter im Baum. */
             neu = &knoten->links;
             knoten = knoten->links;
          }
       }
    }
    

    Es soll in einen binären Baum ein neuer Eintrag der Struktur mit PLZ und dem dazugehörigen Ortsnamen erfolgen.
    Alles soweit sogut, nur warum muss ich hier noch die Variable "neu" mitschlüren?
    Sie ist obendrein noch ein Zeiger auf einen Strukturzeiger.
    Ich habe die neu-Variable komplett rausgenommen und das Programm hat wohl tatsächlich keinen neuen Eintrag gemacht, denn die Suchfunktion hat einen Eintrag, den ich mit dieser Funktion getätigt habe tatsächlich nicht gefunden.
    Ich habe auch den doppelten Zeiger von neu auf einfachen Zeiger umgewandelt, das Ergebnis wieder das gleiche: die Suchfunktion hat nichts gefunden.
    Es funktioniert tatsächlich nur, wenn es diese neu-Variable gibt und zwar als Zeiger auf einen Strukturzeiger des entsprechenden Typs. HÄÄÄÄ ????

    Auf Wunsch kann ich das ganze Listing zur Verfügung stellen, wenn ihr wollt.
    Ich verstehe nicht, warum es diesen doppelzeiger neu geben muss, zumal sie nur immer mitzugewiesen wird, aber sonst nichts mit ihr geschieht.

    schon mal Danke für die Antworten!



  • Hallo,

    der Trick passiert in Zeile 9. Wenn Du den neuen Speicher nur "knoten" zuweist, gibt es keine Verbindung mit dem "baum", den Du als Parameter mitbekommen hast.

    Für den einfachen Fall, dass baum->root am Anfang NULL ist, kannst Du das ja mal Schritt für Schritt durchgehen:

    Ohne neu:

    Zeile 5: knoten wird auch NULL zugewiesen.
    Zeile 9: knoten wird die neue Adresse aus dem malloc zugewiesen. baum->root ist immer noch NULL.
    

    Mit neu:

    Zeile 4: neu wird die Adresse des Zeigers zugewiesen, der auf baum->root zeigt.
    Zeile 9: Wenn Du jetzt "*neu" (nicht "neu") die neuen Adresse aus dem malloc zuweist, änderst Du damit direkt baum->root, den "neu" zeigt genau dorthin.
    


  • Danke DJohn, das bringt mich dem Verständnis schon viel näher.
    Kann ich dann von der Annahme ausgehen, dass "knoten" (als Strukturzeiger) und "neu" (als Zeiger auf den selben Strukturzeiger) vom Compiler verschieden interpretiert würden in den folgenden Zeilen:

    knoten = malloc(sizeof *knoten);
    

    und

    *neu = malloc(sizeof *knoten);
    

    nämlich als neue Adresse für knoten, das von malloc geliefert wird (obere Zeile)
    und (untere Zeile) als neue Adresse für den baum->root Zeiger, weil neu auf die Adresse des baum->root Zeigers zeigt?

    Ist schon recht verwirrend finde ich 😕
    Kann man das nicht besser lösen als in dem Code zur Funktion?



  • Hallo,

    cilker schrieb:

    Kann ich dann von der Annahme ausgehen, dass "knoten" (als Strukturzeiger) und "neu" (als Zeiger auf den selben Strukturzeiger)

    Das passt nicht richtig zusammen. Was ist ein Strukturzeiger?

    konten ist ein Zeiger auf den Typ "struct binaer_knoten"
    neu ist ein Zeiger auf einen Zeiger auf den Typ "struct binaer_knoten". Das ist nicht dasselbe!

    cilker schrieb:

    Ist schon recht verwirrend finde ich 😕
    Kann man das nicht besser lösen als in dem Code zur Funktion?

    Ja bei dem Code, den Du gezeigt hast, bekomme ich auch einen Konten im Hirn. Das geht auf jeden Fall einfacher.



  • HAHAHA

    wie würdest du das denn machen DJohn?
    kannst du ad hoc deinen Ansatz kurz skizzieren?


Anmelden zum Antworten