Zeiger und Konstanten
-
Hallo,
ich habe folgenden C++Code:
#include <iostream> using namespace std; int main(int argc, char *argv[]){ const int i = 10; int *pi = (int*) &i; cout << "Adresse von i: " << &i << endl; cout << "Inhalt von pi: " << pi << endl; cout << "i: " << i << endl; cout << "*pi: " << *pi << endl; *pi=1; cout << "&i: " << &i << endl; cout << "pi: " << pi << endl; cout << "i: " << i << endl; cout << "*pi: " << *pi << endl; return 0; }Ausgegeben wird auf der Konsole unter Linux 32 Bit:
Adresse von i: 0xbfa6089c
Inhalt von pi: 0xbfa6089c
i: 10
*pi: 10
&i: 0xbfa6089c
pi: 0xbfa6089c
i: 10
*pi: 1i ist eine Konstante, wobei ich versuche, diese über den Zeiger pi zu ändern. Laut Memory-Dump beim Debuggen mit Eclipse gelingt mir das auch. Nur wird bei der Ausgabe in der Konsole nach dem Setzen von *pi = 1 wird für i der Wert 10 ausgegeben. Wie kann das sein?
Mir geht es bei der ganzen Sachen nur um das Verständnis, weil ich C++ lernen möchte
.Gruß
acelab
-
Schreiben in eine konstante Variable erzeugt undefiniertes Verhalten, d.h. du kannst nicht vorhersagen, was herauskommt, wenn du versuchst den Compiler auszutricksen - das kann in einem SegFault enden oder auch in derart "seltsamen Ausgaben".
(in deinem Beispiel hat der Compiler i vermutlich in ein Register kopiert, weil er davon ausging, daß sie sowieso nicht geschrieben wird)
-
Du darfst Konstanten in C++ eben nicht einfach so ändern.
Und der C++ Compiler darf davon ausgehen dass du es nicht tust, und daher direkt den Wert10einsetzen wenn du irgendwoischreibst.
Dascout << "i: " << i << endl;wird also einfach zucout << "i: " << 10 << endl;- und das ist halt unabhängig davon was du überpiirgendwo in den Speicher geschrieben hast.
Vereinfacht gesagt.
-
Du kannst auch mal versuchen, i als
static const int i = 10;zu definieren, der Speicher liegt nun im readonly-Bereich (global/static). Ein Schreiben in diesem Bereich dürfte auf jeden Fall zum Absturz führen.
-
_Falke schrieb:
Du kannst auch mal versuchen, i als
static const int i = 10;zu definieren, der Speicher liegt nun im readonly-Bereich (global/static). Ein Schreiben in diesem Bereich dürfte auf jeden Fall zum Absturz führen.
Stimmt. Aber wenn ich mein Programm erweitere zu:
#include <iostream> using namespace std; int main(int argc, char *argv[]){ const int i = 10; int *pi = (int*) &i; cout << "Adresse von i: " << &i << endl; cout << "Inhalt von pi: " << pi << endl; cout << "i: " << i << endl; cout << "*pi: " << *pi << endl; *pi=1; cout << "&i: " << &i << endl; cout << "pi: " << pi << endl; cout << "i: " << i << endl; cout << "*pi: " << *pi << endl; int *pi2 = (int*) &i; cout << "pi2: " << pi2 << endl; cout << "*pi2: " << *pi2 << endl; return 0; }Wieso wird dann laut folgender Konsolenausgabe:
Adresse von i: 0xbfaf743c
Inhalt von pi: 0xbfaf743c
i: 10
*pi: 10
&i: 0xbfaf743c
pi: 0xbfaf743c
i: 10
*pi: 1
pi2: 0xbfaf743c
*pi2: 1pi2 zu 1, obwohl für i zuvor 10 ausgegeben wurde. Wenn i in einem Register ist, und *pi=1 diesen Wert nicht verändert hat, dann sollte doch
int *pi2 = (int*) &i;
cout << "pi2: " << pi2 << endl;
cout << "*pi2: " << *pi2 << endl;den Wert 10 für *pi2 ausgeben.
Ich verstehe das nicht!
-
Die Variable i liegt trotz aller Optimierungen noch irgendwo auf dem Stack, sonst könntest du überhaupt nicht ihre Adresse ermitteln oder Pointer definieren, die auf sie zeigen. Das hindert den Compiler aber nicht daran, die direkten Zugriffe auf die Variable zu optimieren (per Register oder wie hustbaer erwähnt per direkte Wert-Ersetzung).
-
CStoll schrieb:
Die Variable i liegt trotz aller Optimierungen noch irgendwo auf dem Stack, sonst könntest du überhaupt nicht ihre Adresse ermitteln oder Pointer definieren, die auf sie zeigen. Das hindert den Compiler aber nicht daran, die direkten Zugriffe auf die Variable zu optimieren (per Register oder wie hustbaer erwähnt per direkte Wert-Ersetzung).
Ok, ich verstehe. Da war das nochmalige Nachfragen ganz sinnvoll.
Danke an Alle!