Hilfe bei Pointern und Dynamischen Speicher
-
buu2188 schrieb:
Habe mal versucht ein Beispiel meines Prof's umzuschreiben
Als Lehrbeispiel ist das vielleicht geeignet, um Umgang mit Pointern zu lernen, aber in der Praxis wirst du diesen Code eher selten bis hoffentlich gar nicht sehen. Grund: keine Fehlerbehandlung, was passiert bei negativen Eingaben und außerdem wäre hier in C++ wohl ein
std::vector<double>
das Mittel der Wahl.buu2188 schrieb:
Ich habe mal das hier zusammen geschnipselt :
int N; char* x = "ABC";
Das ist schon falsch, dir fehlt const: du solltest eine Ausgabe wie "ISO C++11 does not allow conversion from string literal to 'char *'" bekommen. Wenn nicht, dann stell die Warnungen/Fehler richtig ein. Dann funktioniert natürlich auch die folgende Zuweisung auf
x[i]
nicht mehr. Nimm doch eine neue Variable!buu2188 schrieb:
for (int i = 0 ; i < N ; i++) x[i]=0; cout << *x << endl;
Bekomme das aber nur eine Adresse heraus
Warum?
Das wäre merkwürdig. Da sollte keine Adresse rauskommen, sondern nur das Zeichen mit dem Wert 0, das du vermutlich nicht am Bildschirm siehst, sowie der Zeilenumbruch.
Ich glaube, du solltest dich dringend mit ein paar Kommilitonen zusammensetzen und die Grundlagen (was ist ein Zeiger etc.) noch einmal angucken. Das geht vermutlich besser/schneller als hier. Das soll dich aber nicht davon abhalten, hier gern konkrete Dinge nachzufragen.
-
Ein Pointer ist eine Variable, die eine Adresse speichert.
Um an den Wert zu kommen, der an dieser Adresse liegt, muss man den Pointer dereferenzieren. Dafür ist der * Operator oder auch die [] da.
Eine Besonderheit bei Pointern ist, das bei Addition mit einem integralen Typ die Größe des Elements (auf das der Zeiger verweist) berücksichtigt wird.
x[i] ist identisch mit *(x+i)
Der Pointer enthält keine weitere Information darüber, wie groß der Speicherbereich ist, auf den er zeigt.
cout gibt bei einem Pointer dessen Inhalt (Adresse) aus, es sei denn, es ist ein char-Pointer.
Bei char* wird das wie ein C-String behandelt.Das *x ist bei dir aber vom Typ
char
und ist bei dir 0.char* x = "ABC"; // 4 Zeichen 'A', 'B', 'C', 0 for (int i = 0 ; x[i] != 0 ; i++) // als Array cout << x[i] << endl; for (char *p = x; *p; p++) // mit Pointer *p steht für *p != '\0' cout << *p << endl;
Der Zeiger p wird hier gebraucht, da x ja weiterhin auf den Anfang der Zeichenfolge zeigen soll.
-
Vielen vielen Dank für eure Hilfe
-
DirkB schrieb:
x[i] ist identisch mit *(x+i)
Rätselfrage: ist x oder i der Pointer?
-
Andromeda schrieb:
DirkB schrieb:
x[i] ist identisch mit *(x+i)
Rätselfrage: ist x oder i der Pointer?
Ja
-
Andromeda schrieb:
Rätselfrage: ist x oder i der Pointer?
i zeigt halt auf was anderes
-
HansKlaus schrieb:
Andromeda schrieb:
Rätselfrage: ist x oder i der Pointer?
i zeigt halt auf was anderes
Auf was denn?
-
Andromeda schrieb:
DirkB schrieb:
x[i] ist identisch mit *(x+i)
Rätselfrage: ist x oder i der Pointer?
Solange da ein Pointer und ein integraler Typ ist, ist es egal.
Dies ergibt sich aus dem Kommutativgesetz, dass für die Addition gültig ist.
-
Andromeda schrieb:
HansKlaus schrieb:
Andromeda schrieb:
Rätselfrage: ist x oder i der Pointer?
i zeigt halt auf was anderes
Auf was denn?
kommt halt darauf an, welchen wert i hat.
-
der witz ist, dass [] für eingebaute typen auch kommutativ ist.
void foo (int* array, int i){ assert(array[i] == i[array]); }
-
dove schrieb:
der witz ist, dass [] für eingebaute typen auch kommutativ ist.
Das ist kein Witz, sondern die logisch Folgerung daraus.
-
naja ob ich den wert von i als basisadresse nehme und dann den wert von array hinzuaddiere, oder umgekehrt ist ja auch egal.
-
DirkB schrieb:
Andromeda schrieb:
DirkB schrieb:
x[i] ist identisch mit *(x+i)
Rätselfrage: ist x oder i der Pointer?
Solange da ein Pointer und ein integraler Typ ist, ist es egal.
So ist es.
DirkB schrieb:
Dies ergibt sich aus dem Kommutativgesetz, dass für die Addition gültig ist.
Das ergibt sich eher aus der C-Syntax, die sowas erlaubt.
-
DirkB schrieb:
dove schrieb:
der witz ist, dass [] für eingebaute typen auch kommutativ ist.
Das ist kein Witz, sondern die logisch Folgerung daraus.
logisch ist das nicht, nur wenn man wirklich die definition x[y] == *(x+y) ernst nimmt. die ist aber auch nicht absolut/in stein gemeißelt...
struct Foo { int i; int const& operator*() const { return i; } }; Foo operator+(Foo a, int i) { return a; } Foo operator+(int i, Foo a) { return a; } int main() { Foo f { 42 }; *f; //ok *(f+0); //ok *(0+f); //ok f[0]; //ooops }
-
dove schrieb:
DirkB schrieb:
dove schrieb:
der witz ist, dass [] für eingebaute typen auch kommutativ ist.
Das ist kein Witz, sondern die logisch Folgerung daraus.
logisch ist das nicht, nur wenn man wirklich die definition x[y] == *(x+y) ernst nimmt. die ist aber auch nicht absolut/in stein gemeißelt...
struct Foo { int i; int const& operator*() const { return i; } }; Foo operator+(Foo a, int i) { return a; } Foo operator+(int i, Foo a) { return a; } int main() { Foo f { 42 }; *f; //ok *(f+0); //ok *(0+f); //ok f[0]; //ooops }
Wenn man einfach Operatoren umbiegt, kann man natürlich jede Seltsamkeit hinfrickeln. Daher bevorzuge ich C. Bei einem C++-Codeschnipsel weißt du nie, was wirklich passiert.
-
wenn man den []-operator auch noch überlädt, klappts auch.
-
Andromeda schrieb:
Wenn man einfach Operatoren umbiegt, kann man natürlich jede Seltsamkeit hinfrickeln. Daher bevorzuge ich C. Bei einem C++-Codeschnipsel weißt du nie, was wirklich passiert.
ja, das überladen von operatoren ist eines der wesentlichen merkmale von C++. wenn man sich an bestehende konventionen hält, ist das auch überhaupt nicht schlimm. blöd ist es nur, wenn man einen operator falsch implementiert und daher mehr arbeit ausführen lässt, als nötig wäre. in C muss man sich dann eben darauf verlassen, das irgendwelche funktionen, die man aufruft, richtig und gut geschrieben sind.
leider? reicht es eben nicht, operator+ und den dereferenzierungsoperator zu überladen, um dieselbe funktionalittät wie mit zeiger+integral zu bekommen. das ist aber so eine unbedeutende randerscheinung, dass man als normaler C++-anwender damit trotzdem gut leben kann.
-
Kleine Frage man schließt ja in einem char* die letzte Stelle mit einer Null ab.
Wenn ich das hier mache :
char* name = "Darmstadt"; //char* ptmp = name; name[9] = 0 ; cout << name << endl;
Warum stürzt da mein Programm ab ? Laut Debugger macht er alles richtig.
Er erstellt ein Array und an der "9" Stelle gibt er mir eine \0 .Kann es seien das ich durch
char* name = "Darmstadt";
ein Array erzeuge von [i] Stellen und ich dem Array an der 9ten Stelle eine Null angebe und er versucht sie auszugeben und "0" ja kein erlaubter Zustand seien darf?
Oder hat das was mit dem Speicher zu tuen? Weil bei meinem Dynamischen Speicher muss ich ja mit einer NULL \0 abschließen
Mfg
-
Der Compiler gibt eine Warnung aus. Ein Stringliteral stellt einen const char* - eun Zeiger auf einen Speicherbereich, welcher nicht beschrieben werden darf.
-
Und noch eine letzte Frage
Bin dann echt durch und ihr habt mir bisher sehr sehr gut weitergeholfen 1000000 facher Dank dafür... folgendes :char* m_name; char* name = "Darmstadt"; //char* ptmp = name; m_name = new char[9]; m_name = name;
Hab das mal zu Übungszwecken eingetippt und durch den Debugger gejagt zur Verdeutlichung... Kann mir mal einer erklären, warum bei
m_name = name;
( das der Inhalt übernommen wird ist klar ) aber das die Adressen mit übernommen werden ist mir ein Rätsel ... Sind doch beide verschiedene Arrays?
ist das Normal ?
Weil in dem Script meines Profs wird das per For-Schleife realiesert und sozusagen Jeder einzelne Buchstabe ....for (m_curlenName=0;m_curlenName<m_maxlenName;m_curlenName++) { m_name[m_curlenName]=name[m_curlenName]; }