Zeiger auf Zeiger nicht verstanden

Razorhawk

Webdesigner und MSP
Also ich lese hier in meinem Buch etwas von Zeigern auf Zeigern, wie sie z.b. bei Bäumen und zum einfügen in Listen verwendet wird, da es so besser geht.

Aber ich verstehe nicht ganz wo *variable und **variable hinzeigen wenn variable = %anderevariable zugewiesen wurde.
Ich hab dazu mal ein beispiel geschrieben, kann mir aber nicht erklären wie das Ergebnis zustande kommt (dass die Adressen und Inhalte uasgegeben werden schon) :)

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

struct test{
 
        int inhalt;
        struct test *ptr;       
        
};

struct test *liste= NULL;

int main(int argc, char *argv[])
{
    
   int **a, *b, c=5;
   
   b = &c;
   a = &b;
   
   printf("%d\n",*b);
   printf("%d\n",&b);
   printf("%d\n",*a);
   printf("%d\n",**a);   
       
    
    system("PAUSE");
  

}
 
Hallo!

Code:
struct test{
 
        int inhalt;
        struct test *ptr;       
        
};

struct test *liste= NULL;

Reserviert im Speicher Platz für eine Adresse, benennt diese mit "liste" und teilt dem Compiler mit, dass dort ein Objekt vom Typ "struct test" beginnt.

Code:
   int **a, *b, c=5;

a ist ein Zeiger auf ein Objekt (Zeiger auf ein Objekt vom Typ int).
b ist ein Zeiger auf ein Objekt vom Typ int.

Code:
   b = &c;
   a = &b;

b zeibt nun auf das Objekt c.
a zeibt nun auf das Objekt b.

Code:
   printf("%d\n",*b);

gibt die Adresse von c also &c in dezimaler Darsellung aus (also die Stelle im Speicher, an der c liegt).

Code:
   printf("%d\n",&b);

Gibt die Adresse des Objekts b (also den Platz an dem b im speicher liegt) aus.

Code:
   printf("%d\n",*a);

*a = b also das selbe wie

Code:
   printf("%d\n",**a);

*a ist b, *b ist c also ist **a = c (eine gewisse Transitivität in der Operation der Dereferenzierung)

Code:
Typ * x
Typ ** y
Typ z

x=&z;
x===>z

y=&x;
y===>x===>z

in die andere Richtung geht's mit *x, *y und **y... * heißt auch Dereferenzierungsoperator, während & auch Adressoperator heißt.

&Objekt kiefert die Adresse von Objekt im Speicher.
*Objekt liefert den Inhalt der Speicherzelle, deren Adresse in Objekt steht.

(Übrigends, bevor ich es noch vergesse zu erwähnen... in C ist ein Objekt ein benannter Speicherplatz...)

lg
Johannes
 
Also das was du mir erklärst stimmt nicht ganz mit dem überein was ausgegeben wird oder ich habs falsch verstanden wie du es ekrlärt hast :)

denn bei *a wird bei mir die Speicheradresse ausgegeben (2293612) welche die von c ist
bei **a wird mir der Inhalt von c ausgegeben (5)

das gleiche passiert bei b wie bei **a


kurze Frage... seh ich das richtig, dass für Zeiger auch eine Adresse bereitgestellt wird....
wenn ich so recht über lege ist das ja logisch, da ja beim Zeiger gespeichert werden muss wo er hin zeigt ;)
 
Moin Moin,

jeder Zeiger benötigt irgendwo Speicher und wenn es nur vier Byte sind und die müssen irgendwo anfangen (eine (Start-) Adresse haben). Von Nix kommt Nix.

Um das mit den Pointern zu verstehen stell dir einfach mal folgendes vor:
Deine Variable a sei ein Haus.
*a ist dann ein Schild xy, was auf dein Haus zeigt.
**a ist dann ein Schild was auf das Schild xy zeigt.

Ich weiss das Beispiel hinkt etwas passt aber.
(Da die Schilder irgendwo aufgestellt werden müssen, haben auch Zeiger eine Adresse:))

Gruss Michael
 
Mit der Adresse war ja schon klar, als ich es geschreiben hatte :)

So dann geh ich mal weiter:

Was bringt es mir dann rein praktisch einen Zeiger auf einen Zeiger zu erstellen und ich könnte doch dann auch einen Zeiger b haben, der auf Zeiger a zeigt der auf Vraible t zeigt.
Dazu brauch ich doch nicht extra einen **a erstellen oder?

was können diese Zeiger auf Zeiger, was sie für mich unentbehrlich machen.

Also zur Erklärung noch.
Ich hab auch schon gelesen, wozu sie da sind mir ist aber der praktikable gebrauch nicht ganz klar weshalb ich trotzdem noch frage in der Hoffnung, dass mir jemand es besser erklärt als viele Bücher mit ihren ach so langen Beispielen.
 
Ich habe nochmal machgeschmöckert und ich geb mal selbst ein Beispiel zu meiner Frage noch hintendrann.

Nehmen wir mal den typischen Bäumle:

Code:
struct Knoten
{      int Wert;
       struct Knoten *links,*rechts;
}

void einbauen( struct Knoten **w, int Zahl)
{    while (*w!=NULL)
           w = (Zahl < (*w)->Wert) ? &(*w)->links : &(*w)->rechts;
     *w = (struct Knoten *)malloc(sizeof(struct Knoten));
     (*w)->Wert = Zahl;
     (*w)->links = (*w)->rechts = NULL;
     return;
}

Hier sind ja Zeiger auf Zeiger verwendet worden, aber warum sollte es so nicht auch funktionieren:

Code:
struct Knoten
{      int Wert;
       struct Knoten *links,*rechts;
}

void einbauen( struct Knoten *w, int Zahl)
{    while (w!=NULL)
           w = (Zahl < w->Wert) ? &w->links : &w->rechts;
     w = (struct Knoten *)malloc(sizeof(struct Knoten));
     w->Wert = Zahl;
     w->links = w->rechts = NULL;
     return;
}

Ich muss noch sagen unabhängig ob jetzt Sytanxfehler entstanden sind dadurch, dass ich überall ein " * " weggelöscht habe :)
Es geht mir darum, warum der Code nicht auch entsprechend vom Prinzip mit einfachen Pointern funktionieren sollte statt mit Zeigern auf Zeigern.
 
Im ersten Beispiel bekommt der Aufrufer den Wert seines übergeben Pointers geändet (durch das malloc). Bei deinem zweiten Beispiel wird zwar über malloc ein neuer Wert zugewiesen, das sieht aber der Aufrufende nicht. Die neue Adresse geht am Ende der Routine flöten -> Memory Leak
 
Zurück