Zeigerfrage
-
Richard Kaiser im Buch C++ mit dem Borland C++Builder auf S.180 schrieb:
Definiert man die beiden Strings nicht als Arrays, sondern als Zeiger auf char
char* s="0123456789";
char* t="Hallo";ist die Zuweisung
s = t;
möglich: Durch sie wird die Adresse in s durch die Adresse in t überschrieben
und nicht etwa der String t nach s kopiert. Die Adresse des für s reservierten Bereichs
ist damit aber anschließend verloren, falls man sie nicht vorher gespeichert
hat. Dieser Fehler wird eventuell zunächst übersehen: Unmittelbar nach dieser
Zuweisung hat s ja das gewünschte Ergebnis. Falls man jedoch danach den Wert
von s verändert, verändert man damit auch den Wert von t.Das steht aber irgendwie im Widerspruch dazu, wenn ich es selber ausprobiere:
char* s="0123456789"; //s: :00403190 "0123456789" char* t="Hallo"; //t: :0040319B "Hallo" s = t; s = "abcdef"; //s: :004031A1 "abcdef" //t: :0040319B "Hallo"
Wo liegt mein Gedankenfehler, was mache ich falsch?
-
Nun als erstes, kannst du einem char nur EIN zeichen zuordnen und keinen String,
der zeiger zeigt immer nur auf EIN Element, du kannst somit dort EIN Zeichen speichern
und musst ihn anschließend um 1 erhöhen damit er wieder EIN Zeichen speichern kann,
so:char string1[] = "12345"; char string2[] = "abcdef"; char *zeiger1 = string1; // Adresse von erstem Element von string1 char *zeiger2 = string2; // Adresse von erstem Element von string2 zeiger1 = zeiger2; // zeiger1 hat adresse von zeiger 2 nun printf ("Zeiger2: %s\n",zeiger2); printf ("Zeiger1: %s",zeiger1);
Das Zitat ist vollkommen richtig.
-
SirLant schrieb:
zeiger1 = zeiger2; // zeiger1 hat adresse von zeiger 2 nun
Ne, eben nicht. Adresse 004031A1 ist ungleich Adresse 0040319B
Irgendwas stimmt da nicht.
-
Ne, eben nicht. Adresse 004031A1 ist ungleich Adresse 0040319B
Was meinst du mit adresse die Adresse von s und t oder die Adresse auf die s bzw t zeigen.
Die Zuweisung s=t sorgt dafür das der Pointer s auf die Stelle zeigt auf die auch t zeigt.
das heißt aber nicht das die Stelle an der s steht sich ändert.
-
Habe es eben selbst getestet:
#include <stdio.h> int main (void) { char string1[] = "12345"; char string2[] = "abcdef"; char *zeiger1 = string1; // Adresse von erstem Element von string1 char *zeiger2 = string2; // Adresse von erstem Element von string2 zeiger1 = zeiger2; // zeiger1 hat adresse von zeiger 2 nun printf ("Zeiger2: %s\n",zeiger2); printf ("Zeiger1: %s",zeiger1); getch (); return 0; }
Ausgabe:
Zeiger2: abcdef
Zeiger1: abcdef
-
char string1[] = "12345"; char string2[] = "abcdef"; char *zeiger1 = string1; // zeiger1: :0012FEA0 "12345" char *zeiger2 = string2; // zeiger2: :0012FE98 "abcdef" zeiger1 = zeiger2; // zeiger1: :0012FE98 "abcdef" // zeiger2: :0012FE98 "abcdef"
Ok, wenn ich es wie SirLand mache stimmt es, wenn ich es aber so mache wie im Buch beschrieben komme ich nicht zu den gleichen Adressen.
-
lies den Beitrag im Buch nochmal genau
Durch sie wird die Adresse in s durch die Adresse in t überschrieben
Hier steht die Stelle auf die s zeigt wird durch die Stelle auf die t zeigt überschrieben und die Stelle auf die bis dahin zeigte geht verloren . ein typisches memory leak.
Hier steht nicht das die Adresse von s durch die Adress von t ersetzt wird
Das ist genau das was SirLant und ich beschrieben haben
-
#include <stdio.h> int main (void) { char* s="0123456789"; char* t="Hallo"; s = t; printf ("Zeiger2: %s\n",t); printf ("Zeiger1: %s",s); getch (); return 0; }
Ausgabe(wie nicht anderst zu erwarten):
Zeiger2: Hallo
Zeiger1: HalloIch bin mir sicher, das funktioniert bei dir ebenfalls.
-
Nein.
Ich habs gefunden, mein Fehler steckt hier:Schnuckelhase schrieb:
s = "abcdef";
-
Natürlich geht das nicht, das hab ich dir doch oben erklärt:
...der zeiger zeigt immer nur auf EIN Element, du kannst somit dort EIN Zeichen speichern
und musst ihn anschließend um 1 erhöhen damit er wieder EIN Zeichen speichern kann...
-
Vielen Dank für Eure Mühe bisher.
Ich bin ein ganz dummer Anfänger, ich kapiers immer noch nicht. Warum wird denn die Adresse und der Wert von s durch die Zuweisung "s="abcdef"" verändert?char* s="0123456789"; //s: :00403190 "0123456789" char* t="Hallo"; //t: :0040319B "Hallo" s = t; //s: :0040319B "Hallo" //t: :0040319B "Hallo" s = "abcdef"; //s: :004031A1 "abcdef" //t: :0040319B "Hallo"
-
Hi,
das ist ganz einfach:
wenn Du schreibst char *s="Hallo" , dann wird die Zeichenkette "Hallo" irgendwo im Ram abgelegt, und die Adresse wird in s gespeichert. Wenn Du nun mit s="Test" s einen neuen WErt zuweist, dann wird "Test" an einer anderen Stelle abgelegt, und der wert wieder in s gespeichert. Daher ist die Adresse dann auch anders.
grüße Con@n
-
PAD schrieb:
ein typisches memory leak.
naja, schlimm ist es wenn man Speicher anfordert und nicht wieder freigibt, das hier ist Compilersache.
-
Genau das passiert hier ja die pointer s zeift auf "sinnvolle" Daten und wird durch t überschrieben. damit ist der Speicher auf die s zeigte nicht mehr zugreifbar
-
willst du mir jetzt erzählen das
char* p = "hallo";
Speicher anfordert, den man selber wieder freigeben muss?
Wo is'n da ein "Memory-Leak"?
-
Freigeben muß man den nicht, aber wenn man den Pointer darauf überschreibe kommt man nicht mehr dran.
-
ja und? unter einem memoryleak versteh ich aber was anderes.
-
Schnuckelhase,
Schnuckelhase schrieb:
... Warum wird denn die Adresse und der Wert von s durch die Zuweisung "s="abcdef"" verändert?
char* s="0123456789"; //s: :00403190 "0123456789" char* t="Hallo"; //t: :0040319B "Hallo" s = t; //s: :0040319B "Hallo" //t: :0040319B "Hallo" s = "abcdef"; //s: :004031A1 "abcdef" //t: :0040319B "Hallo"
betrachte die drei Zeichenketten in Deinem Code als Variablen bzw. Container konstanter Größe. Jede Position dieser Zeichenketten im Speicher ist durch einen "Zeiger-Wert" (Addresse) definiert - also hast Du insgesamt 3 davon.
Bei der Zuweisungs = "abcdef";
überschreibst Du lediglich den Zeiger-Wert 0040319B ("Hallo") mit 004031A1 ("abcdef"). Anders gesprochen "biegst" Du nur die Zeiger-Variable s von 0040319B auf 004031A1 um. Die 3 Zeichenketten selbst werden dadurch nicht beeinflußt.
Ein Zeiger ist ein wenig wie ein Link auf dem Desktop. Wenn Du ein anderes Ziel (Addresse) einträgst, ändert sich dessen Verhalten.
(Das ist natürlich ein mangelhafter Vergleich.)
-
Vielen Dank!
Dieses Beispiel 10 Seiten später im Buch hat mir das auch noch mal klar gemacht:
const char* cs1="Zeiger auf Konstante"; *(cs1+1)='G'; // Fehler: const-Objekt nicht modifizierbar cs1="verändere die Konstante"; // das geht char* const cs2="konstanter Zeiger"; *(cs2+11)='G'; // das geht cs2="Geiger"; // Fehler: const-Objekt nicht modifizierbar