Zeigergeschichte
-
Hallo,
ich beschäftige mich in letzter Zeit intensiv mit Zeigern (bin ja noch blutiger Anfänger
) und habe ein paar Fragen dazu.const char * x; x = "Hallo!"; cout << x << "\n"; x = "Hello!"; // warum kann ich einen CONST char * ändern bzw. was ist daran konstant? cout << x << "\n";Was für ein Vorteil(e) har char * gegenüber const char *?
char * s; INT32 * n; s = "Hallo!"; // warum übergebe ich hier ein String-Literal und nicht eine Adresse ? n = 12; // FEHLER! Hier wird eine Adresse erwartet (mit &-Operator). Warum auch nicht oben?Wäre nett, wenn man mich aufklären würde.
Danke im Voraus!
MfG
Seikuassi
-
Seikuassi schrieb:
const char * x; x = "Hallo!"; cout << x << "\n"; x = "Hello!"; // warum kann ich einen CONST char * ändern bzw. was ist daran konstant? cout << x << "\n";In Verbindung mit Zeigern gibt es 2 const. Du musst die Deklaration von rechts nach links lesen. x is a pointer to const-char. D.h. nicht x ist const, sondern das, worauf der Zeiger zeigt. Bei
char* const xwäre der Zeiger const.Seikuassi schrieb:
Was für ein Vorteil(e) har char * gegenüber const char *?
char * s; INT32 * n; s = "Hallo!"; // warum übergebe ich hier ein String-Literal und nicht eine Adresse ? n = 12; // FEHLER! Hier wird eine Adresse erwartet (mit &-Operator). Warum auch nicht oben?Naja, wenn etwas nicht geändert werden soll, machst du es const. Du machst es eben immer so, wie du es brauchst. Wenn etwas änderbar sein soll, kannst du es ja nicht cosnt machen... Also ich würde hier nicht von Vorteil/Nachteil reden. Nun noch zu dem konkreten Beispiel. Literale sind immer konstant, auch Zeichenkettenliterale ("Hallo"). Streng genommen, ist
char* s = "Hallo"also nicht erlaubt.
-
Seikuassi schrieb:
Was für ein Vorteil(e) har char * gegenüber const char *?
Keinen.
char * s; INT32 * n; s = "Hallo!"; // warum übergebe ich hier ein String-Literal und nicht eine Adresse ? n = 12; // FEHLER! Hier wird eine Adresse erwartet (mit &-Operator). Warum auch nicht oben?Ein String-Literal ist ein Array mit statischer Speicherdauer, und wie das bei Arrays so ist, wird jede Erwähnung eines solches Arrays bei jeder sich bietenden Gelegenheit sofort in einen Zeiger auf das erste Element umgewandelt. Im Prinzip könnte da auch sowas stehen:
static char const hallo[] = "Hallo!"; ... s = hallo;Bei int-Literalen ist das nicht so, das sind wirklich einfach nur Zahlen.
BTW dass das mit char* funktioniert, obwohl das Stringliteral const ist, ist ein Spezialfall, den es aus historischen Gründen noch gibt. Normalerweise sollte man auf String-Literale grundsätzlich nur const char* zeigen lassen, da es in jedem Fall undefiniertes Verhalten ergibt, ein String-Literal zu verändern.
-
Seikuassi schrieb:
const char * x; x = "Hallo!"; cout << x << "\n"; x = "Hello!"; // warum kann ich einen CONST char * ändern bzw. was ist daran konstant? cout << x << "\n";Was für ein Vorteil(e) har char * gegenüber const char *?
Ein
const char*ist ein Zeiger auf einen konstantencharund kein konstanter Zeiger (das wäre einchar *const). Du änderst da oben nur den Wert des Zeigers und nicht den Wert des Objektes auf das der Zeiger zeigt, also ist alles in Ordnung.Seikuassi schrieb:
char * s; INT32 * n; s = "Hallo!"; // warum übergebe ich hier ein String-Literal und nicht eine Adresse ? n = 12; // FEHLER! Hier wird eine Adresse erwartet (mit &-Operator). Warum auch nicht oben?String Literale sind Objekte vom Typ
const char[n]. Ein Array, wie eben z.B.const char[n], kann implizit in einen Zeiger auf das erste Element umgewandelt werden. Aus Gründen der Kompatibilität mit uraltem C Code (constgab es nicht immer), gibt es in C++ zusätzlich noch die Regelung, dass ein String Literal auch in einenchar*umgewandelt werden kann. Davon sollte man aber selbst in purem C Abstand nehmen und immer korrektconstverwenden...
-
Seikuassi schrieb:
const char * x;
x = "Hallo!";
cout << x << "\n";
x = "Hello!"; // warum kann ich einen CONST char * ändern bzw. was ist daran konstant?
cout << x << "\n";
[/code]const T * ist ein Zeiger auf ein konstantes T, d.h. das Objekt, auf das er zeigt ist über den Zeiger nicht veränderbar, Beispiel:
int a = 5, b = 2; const int *x = &a; *x = 1; // FEHLER: a über x nicht veränderbar x = &b; // ERLAUBT: Änderung der Variablen, auf die der Zeiger zeigt, erlaubtT * const ist ein konstanter Zeiger auf T, d.h. das Objekt ist veränderbar, aber der Zeiger nicht:
int a = 5, b = 2; const int *x = &a; *x = 1; // ERLAUBT: a über x veränderbar x = &b; // FEHLER: Änderung der Variablen, auf die der Zeiger zeigt, verbotenNatürlich geht auch beides:
const T *const, dann ist beides aus dem Beispiel ein Fehler.Was für ein Vorteil(e) har char * gegenüber const char *?
char* kann nicht auf konstanste char zeigen, const char* schon. Stichwort const correctness.
char * s; INT32 * n; s = "Hallo!"; // warum übergebe ich hier ein String-Literal und nicht eine Adresse ? n = 12; // FEHLER! Hier wird eine Adresse erwartet (mit &-Operator). Warum auch nicht oben?Ein Stringliteral liegt im Arbeitsspeicher.
Es ist wie ein konstantes char-Array, was der Programmier erstellt hat.
Weist man das einem Pointer zu, wird das Literal intern zur Anfangsadresse des Arrays im Speicher konvertiert; es ist also eine Adresse.
Ein Zahlliteral ist aber eine Konstante, die im Programmcode steht, man kann zur Laufzeit nicht darauf zeigen, weil sie nicht im Arbeitsspeicher liegt.
Das man zum Zeigen auf Stringliterale, die eigentlich konstant sind und es undefiniert ist, sie zu verändern, nicht const char* verwenden muss, hat historische Gründe und ist die einzige Ausnahme der Regel oben.Edit: LOL, viermal die gleiche Antwort.
-
Hallo,
danke für die vielen Antworten
!Das heißt also, dass ein String-Literal
char * x; x = "Hallo";folgendem Code entspricht, oder?
char * x; x [0] = 'H'; x [1] = 'a'; x [2] = 'l'; x [3] = 'l'; x [4] = 'o';Folgender Code geht nicht, weil also die einzelnen chars konstant sind, oder was
?const char * x; x [0] = 'H'; x [1] = 'a'; x [2] = 'l'; x [3] = 'l'; x [4] = 'o';Letzte Frage: Wie lang darf denn ein const char * maximal sein?
Danke im Voraus!
MfG
Seikuassi
-
Seikuassi schrieb:
Das heißt also, dass ein String-Literal
char * x; x = "Hallo";folgendem Code entspricht, oder?
char * x; x [0] = 'H'; x [1] = 'a'; x [2] = 'l'; x [3] = 'l'; x [4] = 'o';Nein:
Bashar hat den Code gezeigt. Das Beispiel ist insofern falsch, da du keinen Speicher anforderst.Folgender Code geht nicht, weil also die einzelnen chars konstant sind, oder was
?const char * x; x [0] = 'H'; x [1] = 'a'; x [2] = 'l'; x [3] = 'l'; x [4] = 'o';Ja, folgender Code geht nicht (abgesehen davon, dass du wieder keinen Speicher anforderst).
Letzte Frage: Wie lang darf denn ein const char * maximal sein?
So lang wie dir Arbeitsspeicher zugeteilt ist.[/quote]
-
Letzte Frage: Wie lang darf denn ein const char * maximal sein?
Ein char const* ist ein Zeiger. Zuerst mal kein String. Sein Wert ist eine Speicheradresse. Erst wenn du diesem Zeiger etwas entsprechendes zuweist, kannst du ihn als "String" betrachten, weil er dann auf eine nullterminierte Folge von Bytes (einen NTBS) verweist, die Zeichencodes o.ä. sind.
Vielleicht war deine Frage, wie lang kann ein (echtes)
char-Array sein. Das ist vom Standard nicht vorgegeben - Anhang B, implementation quantities, schreibt eine Höchstzahl für Array-Bounds nicht vor. Aber er darf nicht besonders groß sein, da es auf dem Stack liegt. Und der ist meistens etwa ein, zwei MiB groß.Ein C-String, der auf dem Heap liegt, muss irgendwie allokiert worden sein.
std::stringbswp. hat eine Memberfunktionmax_size(). Diese gibt einen vom Standard in keinster weise definierten Wert zurück.
GCC schreibt im Header:// The maximum number of individual char_type elements of an // individual string is determined by _S_max_size. This is the // value that will be returned by max_size(). (Whereas npos // is the maximum number of bytes the allocator can allocate.) // If one was to divvy up the theoretical largest size string, // with a terminating character and m _CharT elements, it'd // look like this: // npos = sizeof(_Rep) + (m * sizeof(_CharT)) + sizeof(_CharT) // Solving for m: // m = ((npos - sizeof(_Rep))/sizeof(CharT)) - 1 // In addition, this implementation quarters this amount.Allerdings ist das nicht ausschlaggebend, sondern im Endeffekt der Arbeitsspeicher (oder wie viel die OS-spezifische API da hergibt).