Frage zu Zeigern
-
Hallo,
ich benutze Dev-C++ unter WinXP und habe eine Frage zu Zeigern. Ich erlerne gerade C++ aus einem Taschenbuch und wegen der knappen Erklärungen dort habe ich etwas nicht verstehen können. Hier erst mal der kurze Quellcode
char *satz = "Hier bin ich!"; // (1)
cout << satz << " " << *satz ; // (2)In Zeile (1) wird doch der Zeiger "satz" nicht nur definiert (dann hiesse es doch schlicht: "char * satz;"), sondern man weist dem Speicherbereich, auf dessen Anfang er zeigt, zugleich den Wert "Hier bin ich!" zu. So habe ich das zumindest verstanden.
In Zeile (2) sollte nun zunächst mit "cout << satz ..." doch die _Speicheradresse_ des Zeigers "satz" ausgegeben werden, so wie das normalerweise der Fall ist. Stattdessen wird hier aber "Hier bin ich!" ausgegeben...
Dagegen ist die Ausgabe von "cout << *satz" für mich nachvollziehbar, da hier der durch das Sternchen * der _Inhalt_ derjenigen Speicherstelle ausgegeben wird, auf die "satz" zeigt, nämlich "H".
Wo liegt denn nun bei "cout << satz ..." mein Denkfehler?
Danke für die Hilfe,
Tom
-
Is en bischen schwer zu erklaeren. Bei Char verhealt cout sich anders als bei anderen Variablen. Es liest bei char-zeigern nicht die Adresse sondern den Wert aus und zwar solange bis es eine binaere 0 findet. Die wird so wie der Zeiger definiert und direkt initialisiert wird automatisch angehaengt. Wuerdest du den Zeiger selbst per Index initialisieren und wuerdest so noch mal ausgeben, dann wuerde das cout Speicher auslesen bis ne Zugriffsverletzung kommt oder ne 0..
-
Tom_Noob schrieb:
In Zeile (2) sollte nun zunächst mit "cout << satz ..." doch die _Speicheradresse_ des Zeigers "satz" ausgegeben werden, so wie das normalerweise der Fall ist.
Nicht ganz. 'char*' bzw 'const char*' ist in C++ nicht nur ein Zeiger auf ein Zeichen bzw ein Feld von Zeichen, sondern auch zufälligerweise der Typ für C-Strings. Das wird von cout entsprechend beachtet, weshalb auch die Ausgabe des Wertes erfolgt und nicht die Adresse. Diese kann man aber trotzdem ausgeben, indem man zB den Zeiger nach 'void*' castet.
Tom_Noob schrieb:
Dagegen ist die Ausgabe von "cout << *satz" für mich nachvollziehbar, da hier der durch das Sternchen * der _Inhalt_ derjenigen Speicherstelle ausgegeben wird, auf die "satz" zeigt, nämlich "H".
Richtig, nennt sich auch Dereferenzieren. Den gleichen Effekt hast du übrigens, wenn du
cout << satz[0];
schreibst, was für Felder irgendwie auch logischer ist.
-
Du kannst die Adresse auch einfach mit cout << &satz; ausgeben
Das & ist der Adressoperator
-
PunI$0R schrieb:
Du kannst die Adresse auch einfach mit cout << &satz[0]; ausgeben;
Und was soll das bringen? &satz[0] ist vom Typ 'char*', dann kannst du genauso gut satz hinschreiben. Ist letztendlich das gleiche.
Irgendwie war das schon der zweite sinnlose Beitrag von dir, den ich heute lese. Bitte vorm posten erst Gehirn einschalten.
-
ich habs ja noch editiert, sry.. Hmm so neben der Arbeit, sollte ich lieber nich so versuchen hier was zu erklaeren.. Naja
-
PunI$0R schrieb:
cout << &satz;
Sieht zwar schon besser aus, ist aber auch falsch. Hier gibst du lediglich die Adresse aus an welcher sich der Zeiger befindet, nicht aber die Adresse selbst, auf die der Zeiger verweist.
-
Ok, sry ich sollte echt lieber mein C++ hier auf der Arbeit proggen und nur lesen was andere schreiben.. Naja hmm, irgendwie bin ich nich ganz bei der Sache glaub ich..
-
Man kann die Adresse von dem was in satz steht nicht ausgeben!? Jedenfalls nicht mit cout. Oder sehe ich das jetzt wieder Falsch?
-
Doch kann man, indem man sie vorher nach void* castet. (Wie bereits von groovemaster erwähnt.)
Beispiel:
int main() { char* cstr = "Hallo Welt!"; cout << " cstr: " << cstr << endl; cout << " *cstr: " << *cstr << endl; cout << " &cstr[0]: " << static_cast<void*>(cstr) << endl; return 0; }
//Edit:
Zu Arrays und Pointern siehe auch C++-FAQ, Thread: Arrays und Pointer. (Dort ist das alles recht gut erklärt)Caipi
-
Tom_Noob schrieb:
char *satz = "Hier bin ich!"; // (1)
cout << satz << " " << *satz ; // (2)In Zeile (1) wird doch der Zeiger "satz" nicht nur definiert (dann hiesse es doch schlicht: "char * satz;"), sondern man weist dem Speicherbereich, auf dessen Anfang er zeigt, zugleich den Wert "Hier bin ich!" zu. So habe ich das zumindest verstanden.
Nein, anders herum. Der String "Hier bin ich!" wird vom Compiler (zusammen mit allen anderen Stringliteralen) irgendwo im Speicher global verfügbar abgelegt, und satz wird auf die Anfangsadresse dieses Literals initialisiert.
Wär es so wie du sagtest, würde ja irgendwelcher zufälliger Speicher (satz ist ja nicht initialisiert) beschrieben werden.
Definierst du statt einem Zeiger ein Array, also
char satz[] = "Hier bin ich!";passiert übrigens genau das, was du sagst. Allerdings ist satz hier ja kein uninitialisierter Zeiger, sondern ein auf dem Stack liegendes Array.
-
*g* war mal mal kurz bei dem anderen Azubi. Wir hamms jetzt auch wieder
Hmm hat mich eben alles bischen verwirrt
-
Hallo Leute,
vielen Dank für eure Antworten, jetzt sehe ich schon klarer.
Außerdem werde ich mir mal diesen Thread zu den Pointern durchlesen, denn mein C++-Taschenbuch (Helmut Erlenkötter: C++ Objektorientiertes Programmieren von Anfang an) ist oft doch etwas zu knapp.Eine Frage habe ich aber noch:
spielt es denn keine Rolle, wo das Sternchen "*" steht? Bedeutenchar* satz = "Hier bin ich!"; char * satz = "Hier bin ich!"; char *satz = "Hier bin ich!";
stets das gleiche?
Nochmals danke und Gruß
Tom
-
Es ist egal, wo das Sternchen steht. Das ist Geschmackssache. Der Compiler sieht da keinen Unterschied. Ich setzte es immer so
char* p;
Ich kenne auch viele, die es so setzten:
char *p;
-
Alles klar, danke.
Gruß
Tom