[Home]
für Einsteiger!
Seite:  [1] 2 - Drucken

Inhalt:


Pointer & Addressen

Weiter geht's etwas praxisbezogener!

Addresse einer Variable herausfinden und abspeichern

Um die Addresse einer Variablen abspeichern zu können, benötigen wir einen Pointer. Ein Pointer ist quasi ein neuer Datentyp, der Addressen speichern kann. Damit man sich nicht soviel merken muss, hängt man an die Datentypbezeichnung einfach ein "*" an:
Quelltext
  1. //Variable:
  2. int test=3;
  3.  
  4. //Pointer für "int"s:
  5. int* ptest;
  6.  

 
Nun können wir die Addresse mit dem Addressoperator ("&") herausfinden und im Pointer speichern:
Quelltext
  1. //Variable:
  2. int test=3;
  3.  
  4. //Pointer für "int"s:
  5. int* ptest;
  6.  
  7. //Addresse herausfinden und speichern:
  8. ptest=&test;
  9.  

 
Mithilfe des Pointers können wir jetzt entweder die Addresse auslesen, oder mithilfe eines vorangestellten Sternchens (Indirektionsoperator) der Inhalt der Variable, auf die der Pointer zeigt:
Quelltext
  1. //Variable:
  2. int test=3;
  3.  
  4. //Pointer für "int"s:
  5. int* ptest;
  6.  
  7. //Addresse herausfinden und speichern:
  8. ptest=&test;
  9.  
  10. //Nun die Addresse und den Inhalt ausgeben:
  11. std::cout << "ptest = " << ptest << std::endl
  12. << "*ptest = " << *ptest << std::endl;
  13.  

 
Die Ausgabe (Beispiel):
$ ./poi3
ptest = 0xbfebbde8
*ptest = 3
Pointer

Warum?

Das ist ja alles schön und gut, aber warum sollte man das jetzt brauchen? Nun, es gibt da schon einige Einsatzgebiete:

Call by Reference - Pointer als Parameter

Um zwei Variablen zu tauschen benutzt man eine weitere, temporäre:
Quelltext
  1. int var1 = 3;
  2. int var2 = 5;
  3.  
  4. //Tauschen:
  5. int temp=var1;
  6. var1=var2;
  7. var2=temp;
  8.  

 
Wenn du diese Abfolge nun in eine Funktion packen willst, die die beiden Variablen als Parameter akzeptiert, werden zuerst lokale Variablen angelegt, diese dann zugewiesen, getauscht und gelöscht...
Quelltext
  1. //Tauschen: (Funktion mit Fehlern)
  2.  
  3. void tausche(int zahl1, int zahl2)
  4. {
  5. int temp=zahl1;
  6. zahl1=zahl2;
  7. zahl2=temp;
  8. }
  9.  

 
Übergibst du stattdessen nur die Addressen, kannst du die Werte allerdings tauschen! In diesem Fall handelt es sich um Durchgangsparameter! Dieses Prinzip nennt man "Call-by-reference"! Die bisherigen Varianten basierten auf dem Prinzip "Call-by-value", da die Werte nur in die Funktion gelangen, aber nichts wieder herausgeht! ("Eingangsparameter")
 
Mit disem Wissen ausgestattet können wir nun auch unsere Tauschen Funktion korrigieren!
Quelltext
  1. //Tauschen: (Funktion ohne Fehler)
  2.  
  3. void tausche(int* zahl1, int* zahl2)
  4. {
  5. int temp=*zahl1; //Die Werte werden getauscht...
  6. *zahl1=*zahl2;
  7. *zahl2=temp;
  8. }
  9.  
  10. //Beispielaufruf:
  11. int a=3;
  12. int b=5;
  13. tausche(&a,&b); //Addressen übergeben!
  14.  

 
Mit Hilfe der Zeiger haben wir nun eine gute(?) Möglichkeit, mehrere Variablen aus einer Funktion zurückzugeben! Außerdem werden keine Kopien an eine Funktion übergeben, sondern nur die kleinen Addressen, wodurch Zeit und Speicherplatz gespart werden, sobald man mit großen Datentypen oder Objekten (OOP) arbeitet!
Versuche nicht, einen Pointer auf eine lokale Variable zurückzugeben! Das Programm wird wahrscheinlich abstürzen, da du auf einen Speicher zugreifst, den das Programm wieder abgegeben hat! (Ist nunmal "lokal")

Wie geht's weiter?

Bis jetzt haben wir allerdings noch keinen Speicher dynamisch allokiert (d.h.: angelegt), sondern nur die Addressen von Variablen gespeichert, die auf dem Stack liegen, der ja bekanntlich nur eine begrenzte Größe hat! Auf der nächsten Seite geht es daher um das dynamische anlegen auf dem Heap!
Seite:  [1] 2 - Drucken