Pointer. Grundsätzliches: Im Arbeitsspeicher werden Daten gespeichert. Um auf die Daten eindeutig...
-
Upload
birgit-winter -
Category
Documents
-
view
216 -
download
2
Transcript of Pointer. Grundsätzliches: Im Arbeitsspeicher werden Daten gespeichert. Um auf die Daten eindeutig...
Pointer
Grundsätzliches:
Im Arbeitsspeicher werden Daten gespeichert. Um auf die Daten eindeutig zugreifen zu können, werden diesen Daten Adressen zugeordnet. Diese sind fest eingebrannt und können nicht durch ein Programm verändert werden. Verändert werden können nur die Daten.
Vergleich:Jedes Haus hat eine feste Adresse, die von einem Amt fest vorgegeben werden und vom Hauseigentümer nicht verändert werden dürfen. Nur die in jedem Haus wohnenden Menschen können geändert werden (z.B. Wohnungswechsel).
Man kann sich einen Arbeitsspeicher schematisch wie folgt vorstellen:
Ausschnitt aus einem ArbeitsspeicherAdresse Wert0 ...1 ...2 ...3 ...4 ...... ...... ...
Fest eingebrannte, unveränderliche Werte
veränderliche Werte (die durch ein Programm geändert werden können).Wenn nichts anderes angegeben wird, besteht der Wert immer aus 1 Byte. Also ist 1 Byte die kleinste adressierbare Speichereinheit.
Durch die Deklaration einer Variable wird im Arbeitsspeicher an einer bestimmten Adresse Platz reserviert.Wird zusätzlich bei der Deklaration die Variable noch z.B. mit 5 initialisiert, bekommt der Wert an dieser Adresse 5 zugewiesen.Wird die Variable nicht initialisiert, ist der Wert an dieser Adresse unbestimmt (undefiniert).
Bitte folgendes Programm abschreiben
...int x = 5;int *ptr;ptr = &x;*ptr = 13;
0123 5x...
...
Programm-Ausschnitt
Arbeitsspeicher -Ausschnitt
Was veranlasst diese Anweisung im Arbeitsspeicher ?
Es wird im Arbeitsspeicher an einer bestimmten Adresse Platz für eine integer-Zahl reserviert und die Zahl 5 der Variablen x zugewiesen.
Auf die (Anfangs)Adresse dieses Speicherbereichs hat der Programmierer keinen Einfluß. Diese legt der Compiler bzw. Programmlader fest.
Adresse Wert
...int x = 5;int *ptr;ptr = &x;*ptr = 13;
0123 5x...
0456 0815ptr...
Programm-Ausschnitt
Adresse Wert
Inhalt von
Adresse von
Deklaration eines Pointers: d.h. Wert von
ptr ist eine Adresse
Compiler speichert hier in Wirklichkeit die Variablen direkt hintereinander ab (Speicher wird
nicht fragmentiert).
Arbeitsspeicher -Ausschnitt
Wert undefiniert: wir nehmen diesen Wert einfach mal an.
...int x = 5;int *ptr;ptr = &x;*ptr = 13;
0123 5x...
0456 0815ptr...
Programm-Ausschnitt
Adresse Wert
Arbeitsspeicher -Ausschnitt
...int x = 5;int *ptr;ptr = &x;*ptr = 13;
0123 5x...
0456 0123ptr...
Programm-Ausschnitt
Adresse Wert
Arbeitsspeicher -Ausschnitt
...int x = 5;int *ptr;ptr = &x;*ptr = 13;
0123 5x...
0456 0123ptr...
Programm-Ausschnitt
0123
Adresse Wert
Arbeitsspeicher -Ausschnitt
...int x = 5;int *ptr;ptr = &x;*ptr = 13;
0123 13x...
0456 0123ptr...
Programm-Ausschnitt
0123
Adresse Wert
Arbeitsspeicher -Ausschnitt
Ein Pointer ist eine Variable, deren Wert die Adresse eines
Speicherplatzes (z.B.einer Variable) ist.
Merke:
Unterschied Pointer und "normaler" Wert im Arbeitsspeicher. Dazu ein Beispiel aus
dem "Alltag":Bei Absitzen einer Gefängnisstrafe muß
sich eine Person ("normaler" Wert) in der Zelle (Teil des Arbeitsspeicher) befinden.
Es ist nicht zulässig, statt einer Person ("normaler" Wert) eine Telefonnumer
(Adresse) zu hinterlegen.
Ein Pointer ist also ein Verweis.
Man sagt dazu auch Zeiger, Referenz, Link
Beispiel:
Bitte folgende Aufgabe 1 in Gruppen zu je zwei Leuten lösen (siehe Aufgabenblatt
oder folgende Folie)
...int a = 7;int b = 3;int c = 5;int *ptr;ptr = &a;a = a + b + c;
01350 7a...
02460 3b...
03570 5c...
04680 04711ptr...
Aufgabe: Welchen Wert hat *ptr nach Programmende ?
Wert undefiniert: wir nehmen diesen Wert einfach mal an.
...int a = 7;int b = 3;int c = 5;int *ptr;ptr = &a;a = a + b + c;
01350 7a...
02460 3b...
03570 5c...
04680 04711ptr...
...int a = 7;int b = 3;int c = 5;int *ptr;ptr = &a;a = a + b + c;
01350 7a...
02460 3b...
03570 5c...
04680 01350ptr...
...int a = 7;int b = 3;int c = 5;int *ptr;ptr = &a;a = a + b + c;
01350 7a...
02460 3b...
03570 5c...
04680 01350ptr...
...int a = 7;int b = 3;int c = 5;int *ptr;ptr = &a;a = a + b + c;
01350 15a...
02460 3b...
03570 5c...
04680 01350ptr...
Welchen Wert hat *ptr 1501350
Beispiel:
Bitte folgende Aufgabe 2 in Gruppen zu je zwei Leuten lösen (siehe Aufgabenblatt
oder folgende Folie)
...float e = 3.1;float f = 2.7;float *p;p = &e;*p = f +*p;
01350 3.1e...
02460 2.7f...
03570 0007p...
Aufgabe: Welchen Wert hat e nach Programmende ?
Wert undefiniert: wir nehmen diesen Wert einfach mal an.
...float e = 3.1;float f = 2.7;float *p;p = &e;*p = f +*p;
01350 3.1e...
02460 2.7f...
03570 0007p...
...float e = 3.1;float f = 2.7;float *p;p = &e;*p = f +*p;
01350 3.1e...
02460 2.7f...
03570 01350p...
...float e = 3.1;float f = 2.7;float *p;p = &e;*p = f +*p;
01350 3.1e...
02460 2.7f...
03570 01350p...
01350
2.7
013503.1
...float e = 3.1;float f = 2.7;float *p;p = &e;*p = f +*p;
01350 5.8e...
02460 2.7f...
03570 01350p...
Welchen Wert hat e
5.8
01350
2.7
013503.1
Pointer und Felder
...int v[3] = {20,5,10};...
0138 20v[0]? 5v[1]? 10v[2]
...
Aufgabe: Wie heißen die Adressen von v[1] und v[2] Tipp: Debugger von Visual C++ benutzen
Bitte folgende Aufgabe 3 in Gruppen zu je zwei Leuten lösen (siehe Aufgabenblatt
oder folgende Folie)
...int v[3] = {20,5,10};...
0138 20v[0]0142 5v[1]0146 10v[2]
...
013801390140014101420143014401450146014701480149
0 0
2 0
0 0 0
50 0 1 0
daß die Zahl 20 vier Byte,die Zahl 5 vier Byte und die Zahl 10 auch 4 Byte belegt ...
Die Darstellung rechts ist eine Abkürzung für die Darstellung
links (folgt gleich) und bedeutet ...
0138 200142 50146 10
int braucht 4 Byte. Wie die Zahlen (20 bzw. 5 bzw. 10) jeweils auf die 4 Byte verteilt wird, ist für uns uninteressant.Falls es jemand interessiert (nächste Folie)
013801390140014101420143014401450146014701480149
0138 200142 50146 10
Dualdarstellung (als 4 Byte) von 20 ist:0001010000000000
0000000000000000
0001010000000000 00000000 00000000
Das 1. Byte kommt nach ...
Das 2. Byte kommt nach ...
Das 3. Byte kommt nach ...
Das 4. Byte kommt nach ...
Aufgabe: Bestimmen Sie die restlichen Bytes dieser Tabelle
0000010100000000000000000000000000001010000000000000000000000000
Bitte Aufgabe 4 in Gruppen zu je zwei Leuten lösen
(siehe Aufgabenblatt oder folgende Folie)
...double d[3] = {3.1,2.7,6.2};...
0100 3.1d[0]? 2.7d[1]? 6.2d[2]
...
Aufgabe: Wie heißen die Adressen von v[1] und v[2] Tipp: Debugger von Visual C++ benutzen
...double d[3] = {3.1,2.7,6.2};...
0100 3.1d[0]0108 2.7d[1]0116 6.2d[2]
...
Ergebnis
Die Adresse hängt von der Grösse des Datentyps ab.
Beispiel:Wie entwickeln sich die Werte (in der Tabelle) der folgenden Variablen dynamisch während des Programmablaufs ?
int v[3] = {10,20,30};int *p,*q,*r;
0138 10v[0]0142 20v[1]0146 30v[2]
...0471 0815p0590 0345q
p = &v[0];q = &v[1];r = &v[2];*(p+1)= 3;
*(r-2)= 50;q = r-2;
0634 0765r
*r = *p + *(q+1);p = r;*p = *p + *(q+1) + *(r-2);
Werte undefiniert: wir nehmen diesen
Wert einfach mal an.
0138 10v[0]0142 20v[1]0146 30v[2]
...0471 0138p0590 0345q
*(r-2)= 50;q = r-2;
0634 0765r
*r = *p + *(q+1);p = r;*p = *p + *(q+1) + *(r-2);
int v[3] = {10,20,30};int *p,*q,*r;p = &v[0];q = &v[1];r = &v[2];*(p+1)= 3;
0138 10v[0]0142 20v[1]0146 30v[2]
...0471 0138p0590 0345q
*(r-2)= 50;q = r-2;
0634 0765r
*r = *p + *(q+1);p = r;*p = *p + *(q+1) + *(r-2);
int v[3] = {10,20,30};int *p,*q,*r;p = &v[0];q = &v[1];r = &v[2];*(p+1)= 3;
0138 10v[0]0142 20v[1]0146 30v[2]
...0471 0138p0590 0142q
*(r-2)= 50;q = r-2;
0634 0765r
*r = *p + *(q+1);p = r;*p = *p + *(q+1) + *(r-2);
int v[3] = {10,20,30};int *p,*q,*r;p = &v[0];q = &v[1];r = &v[2];*(p+1)= 3;
0138 10v[0]0142 20v[1]0146 30v[2]
...0471 0138p0590 0142q
*(r-2)= 50;q = r-2;
0634 0765r
*r = *p + *(q+1);p = r;*p = *p + *(q+1) + *(r-2);
int v[3] = {10,20,30};int *p,*q,*r;p = &v[0];q = &v[1];r = &v[2];*(p+1)= 3;
0138 10v[0]0142 20v[1]0146 30v[2]
...0471 0138p0590 0142q
*(r-2)= 50;q = r-2;
0634 0146r
*r = *p + *(q+1);p = r;*p = *p + *(q+1) + *(r-2);
int v[3] = {10,20,30};int *p,*q,*r;p = &v[0];q = &v[1];r = &v[2];*(p+1)= 3;
0138 10v[0]0142 20v[1]0146 30v[2]
...0471 0138p0590 0142q
q = r-2;
0634 0146r
*r = *p + *(q+1);p = r;*p = *p + *(q+1) + *(r-2);
int v[3] = {10,20,30};int *p,*q,*r;p = &v[0];q = &v[1];r = &v[2];*(p+1)= 3;0138 + 1 = 0139*(r-2)= 50;
Wo würde die 3 abgespeichert werden, wenn der Compiler so rechnen würde ? Schauen wir uns den Arbeitsspeicher
genauer an ...
0138v[0]0139
v[1]
014001410142
q = r-2;
0143
*r = *p + *(q+1);p = r;*p = *p + *(q+1) + *(r-2);
int v[3] = {10,20,30};int *p,*q,*r;p = &v[0];q = &v[1];r = &v[2];*(p+1)= 3;0138 + 1 = 0139*(r-2)= 50;
01440145
0 0
1 0
0 0 2 0
Wo würde die 3 abgespeichert werden? Schauen wir uns den Arbeitsspeicher genauer an ...
int braucht 4 Byte. Wie die Zahl (10 bzw. 20) auf die 4 Byte verteilt wird, ist für uns uninteressant
0138v[0]0139
v[1]
014001410142
q = r-2;
0143
*r = *p + *(q+1);p = r;*p = *p + *(q+1) + *(r-2);
int v[3] = {10,20,30};int *p,*q,*r;p = &v[0];q = &v[1];r = &v[2];*(p+1)= 3;0138 + 1 = 0139*(r-2)= 50;
01440145
0 0
1 0
0 0 2
0
ab der Adresse 0139 werden 4 Byte abgespeichert.
0138v[0]0139
v[1]
014001410142
q = r-2;
0143
*r = *p + *(q+1);p = r;*p = *p + *(q+1) + *(r-2);
int v[3] = {10,20,30};int *p,*q,*r;p = &v[0];q = &v[1];r = &v[2];*(p+1)= 3;0138 + 1 = 0139*(r-2)= 50;
01440145
0
0 0 2
0138v[0]0139
v[1]
014001410142
q = r-2;
0143
*r = *p + *(q+1);p = r;*p = *p + *(q+1) + *(r-2);
int v[3] = {10,20,30};int *p,*q,*r;p = &v[0];q = &v[1];r = &v[2];*(p+1)= 3;0138 + 1 = 0139*(r-2)= 50;
01440145
0 0
3 0
0 0 2
0
Es wird nicht ein Speicherblock, sondern (Teile) zweier Speicherblöcke (v[0] und
v[1]) überschrieben: zwei Zahlen "beschädigt" (versaut)
Deswegen rechnet der Compiler bei Adressrechnungen wie folgt ..
0138 10v[0]0142 20v[1]0146 30v[2]
...0471 0138p0590 0142q
q = r-2;
0634 0146r
*r = *p + *(q+1);p = r;*p = *p + *(q+1) + *(r-2);
int v[3] = {10,20,30};int *p,*q,*r;p = &v[0];q = &v[1];r = &v[2];*(p+1)= 3;0138 + 1 *4 = 0142*(r-2)= 50;
!
0138 10v[0]0142 3v[1]0146 30v[2]
...0471 0138p0590 0142q
*(r-2)= 50;q = r-2;
0634 0146r
*r = *p + *(q+1);p = r;*p = *p + *(q+1) + *(r-2);
int v[3] = {10,20,30};int *p,*q,*r;p = &v[0];q = &v[1];r = &v[2];*(p+1)= 3;0138 + 1 *4 = 0142
Bitte diese angefangene Aufgabe (= Aufgabe 5 im Aufgabenblatt) vollends
selbständig lösen.
0138 10v[0]0142 3v[1]0146 30v[2]
...0471 0138p0590 0142q
*(r-2)= 50;q = r-2;
0634 0146r
*r = *p + *(q+1);p = r;*p = *p + *(q+1) + *(r-2);
int v[3] = {10,20,30};int *p,*q,*r;p = &v[0];q = &v[1];r = &v[2];*(p+1)= 3;
0146-2*4 = 0138
0138 50v[0]0142 3v[1]0146 30v[2]
...0471 0138p0590 0142q
*(r-2)= 50;q = r-2;
0634 0146r
*r = *p + *(q+1);p = r;*p = *p + *(q+1) + *(r-2);
int v[3] = {10,20,30};int *p,*q,*r;p = &v[0];q = &v[1];r = &v[2];*(p+1)= 3;
0138 50v[0]0142 3v[1]0146 30v[2]
...0471 0138p0590 0142q
q = r-2;
0634 0146r
*r = *p + *(q+1);p = r;*p = *p + *(q+1) + *(r-2);
int v[3] = {10,20,30};int *p,*q,*r;p = &v[0];q = &v[1];r = &v[2];*(p+1)= 3;
*(r-2)= 50;// 0146-2*4=0138
0138 50v[0]0142 3v[1]0146 30v[2]
...0471 0138p0590 0138q
*(r-2)= 50;q = r-2;
0634 0146r
*r = *p + *(q+1);p = r;*p = *p + *(q+1) + *(r-2);
int v[3] = {10,20,30};int *p,*q,*r;p = &v[0];q = &v[1];r = &v[2];*(p+1)= 3;
0138 50v[0]0142 3v[1]0146 30v[2]
...0471 0138p0590 0138q
*(r-2)= 50;q = r-2;
0634 0146r
*r = *p + *(q+1);
int v[3] = {10,20,30};int *p,*q,*r;p = &v[0];q = &v[1];r = &v[2];*(p+1)= 3;
0138 0138+1 *40146
0138 50v[0]0142 3v[1]0146 30v[2]
...0471 0138p0590 0138q
*(r-2)= 50;q = r-2;
0634 0146r
*r = *p + *(q+1);
int v[3] = {10,20,30};int *p,*q,*r;p = &v[0];q = &v[1];r = &v[2];*(p+1)= 3;
0138 01420146
50 3
0138 50v[0]0142 3v[1]0146 53v[2]
...0471 0138p0590 0138q
*(r-2)= 50;q = r-2;
0634 0146r
*r = *p + *(q+1);
int v[3] = {10,20,30};int *p,*q,*r;p = &v[0];q = &v[1];r = &v[2];*(p+1)= 3;
0138 50v[0]0142 3v[1]0146 53v[2]
...0471 0138p0590 0138q
*(r-2)= 50;q = r-2;
0634 0146r
*r = *p + *(q+1);p = r;*p = *p + *(q+1) + *(r-2);
int v[3] = {10,20,30};int *p,*q,*r;p = &v[0];q = &v[1];r = &v[2];*(p+1)= 3;
0138 50v[0]0142 3v[1]0146 53v[2]
...0471 0138p0590 0138q
*(r-2)= 50;q = r-2;
0634 0146r
*r = *p + *(q+1);p = r;*p = *p + *(q+1) + *(r-2);
int v[3] = {10,20,30};int *p,*q,*r;p = &v[0];q = &v[1];r = &v[2];*(p+1)= 3;
0138 50v[0]0142 3v[1]0146 53v[2]
...0471 0146p0590 0138q
*(r-2)= 50;q = r-2;
0634 0146r
*r = *p + *(q+1);p = r;*p = *p + *(q+1) + *(r-2);
int v[3] = {10,20,30};int *p,*q,*r;p = &v[0];q = &v[1];r = &v[2];*(p+1)= 3;
0138 50v[0]0142 3v[1]0146 53v[2]
...0471 0146p0590 0138q
*(r-2)= 50;q = r-2;
0634 0146r
*r = *p + *(q+1);p = r;*p = *p + *(q+1) + *(r-2);
int v[3] = {10,20,30};int *p,*q,*r;p = &v[0];q = &v[1];r = &v[2];*(p+1)= 3;
0146-24=01380138+14=0142
0146
0138 50v[0]0142 3v[1]0146 106v[2]
...0471 0146p0590 0138q
*(r-2)= 50;q = r-2;
0634 0146r
*r = *p + *(q+1);p = r;*p = *p + *(q+1) + *(r-2);
int v[3] = {10,20,30};int *p,*q,*r;p = &v[0];q = &v[1];r = &v[2];*(p+1)= 3;
Noch ein paar Infos:
Der Wert eines Pointers wird mit%p ausgegeben.Siehe folgendes Beispiel:
int main (){
int zahl=5;
int *ptr;
ptr = &zahl;
printf("Adresse=%p Inhalt=%d", ptr, *ptr);
return 0;
}
Warum macht das folgende Programm während der Laufzeit Probleme?
int main (){
int *ptr;
*ptr = 4711;
return 0;
}
Die Variable ist nicht initialisiert. Deshalb steht in ptr eine uns unbekannte Adresse. An dieser Adresse wurde aber kein Speicher reserviert. Deshalb könnte an dieser Adresse ein Teil des Betriebssystems stehen.
Der Inhalt dieser Adresse ist also nicht reservierter Speicher. Auf diesen wird zugegriffen. Moderne Prozessoren merken dies und deshalb wird auf dem Bildschirm eine entsprechende Meldung ausgegeben.
Konkretes Beispiel: Siehe nächste Folie!
int main (){
int *ptr;
*ptr = 4711;
return 0;}
0815ptr...
0912
0912...
Teildes
Syst.Betr.
Wert undefiniert: wir nehmen diesen Wert einfach mal an.
Was steht an der Adresse 0912 im Arbeitsspeicher ?
Der Programmierer weiß es nicht, denn er hat an dieser Adresse keinen Speicherplatz reservieren lassen und diesen entsprechend belegt.In einem schlimmen Fall könnte an der Adresse 0912 zum Beispiel...
ein Teil des Betriebssystems stehen !
int main (){
int *ptr;
*ptr = 4711;
return 0;}
0815ptr...
0912
0912...
Wert undefiniert: wir nehmen diesen Wert einfach mal an.
Was steht an der Adresse 0912 im Arbeitsspeicher ?
Der Programmierer weiß es nicht, denn er hat an dieser Adresse keinen Speicherplatz reservieren lassen und diesen entsprechend belegt.In einem schlimmen Fall könnte an der Adresse 0815 zum Beispiel...
ein Teil des Betriebssystems stehen !
4 7
1 1