Warum müssen String-Literale (char*) in C++ Konstanten sein?

Lesezeit: 6 Minuten

Benutzer-Avatar
Serket

Ich habe kürzlich C++ gelernt und festgestellt, dass Zeichenfolgenliterale in C++ Konstanten sein müssen, während dies in C nicht der Fall ist. Hier ist ein Beispiel. Der folgende Code wäre in C gültig, aber nicht in C++:

char* str = "Hello World";

Um dasselbe in C++ zu tun, muss die folgende Anweisung verwendet werden:

const char* str = "Hello World";

Könnte jemand erklären warum?

  • ” während sie es in C nicht tun” Sie sind falsch. String-Literale in C sind konstant, aber a darf auf sie zeigen char*. Sie können die Zeichenfolge immer noch nicht über diesen Zeiger ändern. In C++ haben sie diese Ausnahme einfach eliminiert, um die Korrektheit zu erhalten, um Verwirrung und Fehler zu vermeiden.

    – Francois Andrieux

    4. Mai 2020 um 21:26 Uhr


  • Denn so haben sie die Sprache entworfen. C hatte anfangs nicht die const Schlüsselwort, so dass es Legacy-Code beschädigen würde, wenn sie Literale in erforderlich ändern würden const-Qualifikation nach Einführung des Schlüsselwortes. Die Zeichenfolgenliterale von C sind jedoch unveränderlich, sodass das Ändern des Inhalts ein undefiniertes Verhalten ist, selbst wenn dies nicht der Fall ist const-qualifiziert.

    – Christian Gibbons

    4. Mai 2020 um 21:26 Uhr


  • @ChristianGibbons warum funktioniert dann der folgende Code? “char* str = “Hallo Welt”; str = “Auf Wiedersehen Welt”;“`

    – Serket

    4. Mai 2020 um 21:28 Uhr


  • @Serket: Das ändert nicht die Zeichenfolge selbst; es ändert den Zeiger str (was keine Konstante ist), um auf eine andere Zeichenfolge zu zeigen. char *str = "Hello World"; str[0] = 'J'; wäre undefiniertes Verhalten.

    – Nate Eldredge

    4. Mai 2020 um 21:29 Uhr

  • @FrançoisAndrieux, das solltest du wahrscheinlich in eine Antwort kopieren.

    – Marco Bonelli

    4. Mai 2020 um 21:30 Uhr

Erweitern Sie die Antwort von Christian Gibbons ein wenig …

In C werden Zeichenfolgenliterale wie "Hello World" werden in Arrays von gespeichert char so dass sie während der gesamten Lebensdauer des Programms sichtbar sind. String-Literale sind soll unveränderlich sein, und einige Implementierungen speichern sie in einem Nur-Lese-Speichersegment (so dass der Versuch, den Inhalt des Literals zu ändern, einen Laufzeitfehler auslöst). Einige Implementierungen tun dies nicht, und der Versuch, den Inhalt des Literals zu ändern, löst möglicherweise keinen Laufzeitfehler aus (es scheint sogar wie beabsichtigt zu funktionieren). Die C-Sprachdefinition lässt das Verhalten “undefiniert”, so dass der Compiler die Situation frei handhaben kann, wie er es für richtig hält.

In C++ werden String-Literale in Arrays von gespeichert const charsodass jeder Versuch, den Inhalt des Literals zu ändern, eine Diagnose auslöst zur Kompilierzeit.

Wie Christian betont, die const Das Schlüsselwort war ursprünglich kein Teil von C. Es war jedoch ursprünglich Teil von C++ und macht die Verwendung von Zeichenfolgenliteralen ein wenig sicherer.

Denken Sie daran, dass die const Stichwort nicht bedeutet “speichere dies im Nur-Lese-Speicher”, es bedeutet nur “dieses Ding darf nicht das Ziel einer Zuweisung sein”.

Denken Sie auch daran, es sei denn, es handelt sich um den Operanden von sizeof oder unär * Operatoren oder ist ein Zeichenfolgenliteral, das zum Initialisieren eines Zeichenarrays in einer Deklaration verwendet wird, an Ausdruck vom Typ “N-elementiges Array von T” wird in einen Ausdruck vom Typ “Zeiger auf T” und der Wert des Ausdrucks ist die Adresse des ersten Elements des Arrays.

In C++ beim Schreiben

const char *str = "Hello, world";

das die Anschrift des ersten Zeichens der Zeichenfolge gespeichert wird str. Sie können einstellen str auf a zeigen anders String-Literal:

str = "Goodbye cruel world";

aber was du kann nicht ändern Sie den Inhalt der Zeichenfolge, so etwas wie

str[0] = 'h';

oder

strcpy( str, "Something else" );

  • IMO eine richtige Antwort. Ich würde das wahrscheinlich mehr betonen const char *s="foo"; das const sagt nur etwas über den Zeiger aus (kann nicht zum Schreiben verwendet werden), sagt aber nichts über das Objekt aus, auf das gezeigt wird. Leider verwechseln viele C++-Programmierer (und sogar die Standardbibliothek) die beiden besonders mit Referenzen (z const X& x das Stichwort const ist relativ zu Hinweis nur und sagt nichts über das referenzierte Objekt aus; Passieren a const& ist nicht eine clevere Möglichkeit, den Wert zu übergeben, da Sie auf Lebensdauer- oder Aliasing-Probleme stoßen können).

    – 6502

    6. Mai 2020 um 6:08 Uhr

  • @6502: const char *str bedeutet, dass das Objekt, auf das gezeigt wird, ist const, nicht der Zeiger. Wir können einen neuen Wert schreiben str (zeigen Sie es auf ein anderes Objekt), aber nicht auf *str oder str[i]. char * const str bedeutet, dass der Zeiger selbst ist const und kann nicht geschrieben werden, aber das Ding, auf das es zeigt, kann es sein.

    – Johannes Bode

    6. Mai 2020 um 10:58 Uhr

  • Nein. Die Erklärung const char *str; ist eine Deklaration eines “Nur-Lese-Zeigers”, dh eines Zeigers, der nur zum Lesen verwendet werden kann … aber das ist eine Eigenschaft des Zeigers, es sagt nichts über die Konstanz des angezeigten Objekts aus. Das spitze Objekt kann sich ändern, es kann einfach nicht geändert werden mit diesem Zeiger (Aber es kann zum Beispiel andere Lese-/Schreibzeiger auf dasselbe Objekt geben). EIN const char * ist kein Zeiger auf char, das const ist, es ist ein Zeiger auf ein char, das nicht zum Schreiben verwendet werden kann.

    – 6502

    6. Mai 2020 um 12:56 Uhr

  • @6502: =*seufz*= Du hast Recht – ich hatte meinen Kaffee noch nicht getrunken.

    – Johannes Bode

    8. Mai 2020 um 14:05 Uhr

  • @Splines: Code wie char x = 'A'; const char *p = &x; printf("%c\n", *p); x = 'B'; printf("%c\n", *p); ist vollkommen gültig und die Ausgabe muss sein A\nB\n (sehen godbolt.org/z/rjx64TjMG). So p ist kein Zeiger auf eine Konstante, denn worauf gezeigt wird, ändert sich! Sicher, Sie können es nicht mit ändern p (ohne Besetzung), aber das macht das spitze Objekt nicht zu einer Konstante im absoluten Sinne. p ist ein Zeiger, der nicht zum Schreiben verwendet werden kann (deshalb würde ich “readonly pointer” bevorzugen). Beachte das aber Zeichenfolgenliterale SIND Konstanten, daher ist der Versuch, sie zu modifizieren, UB.

    – 6502

    7. Januar um 20:53 Uhr

Benutzer-Avatar
Christian Gibbons

C hatte anfangs nicht die const Schlüsselwort, so dass es Legacy-Code beschädigen würde, wenn sie Literale in erforderlich ändern würden const-Qualifikation nach Einführung des Schlüsselwortes. Die Zeichenfolgenliterale von C sind jedoch unveränderlich, sodass das Ändern des Inhalts ein undefiniertes Verhalten ist, selbst wenn dies nicht der Fall ist const-qualifiziert.

C++ hingegen wurde mit dem entworfen const Stichwort. Anfänglich erlaubte C++ die Zuweisung von String-Literalen zu non const-qualifiziert char *s vermutlich aus Gründen der Kompatibilität mit vorhandenem C-Code. Ab dem C++03-Standard haben sie sich jedoch entschieden, diese Funktionalität zu verwerfen, anstatt zuzulassen, dass die Dissonanz für immer andauert. Ich würde schätzen, wie viel Legacy-C++-Code auf Nicht-const qualifiziert char *s zeigt auf String-Literale, dass sie klein genug sind, dass es ein würdiger Kompromiss wäre.

  • Beachten Sie, dass C++ anfangs nicht-konstante erlaubte char* zu Literalen. Aber es war veraltet und wurde in C++11 offiziell entfernt. Also auch wenn C++ ursprünglich mit entworfen wurde const im Hinterkopf, diese Ausnahme von der Regel wurde es für eine Weile belassen.

    – Francois Andrieux

    4. Mai 2020 um 21:33 Uhr


  • Ja, erst in C++03 wurde das Verhalten als veraltet markiert.

    – NathanOliver

    4. Mai 2020 um 21:34 Uhr

  • Hmm, okay, ich werde versuchen, die beste Formulierung zu finden, um den C++-Winkel der Antwort zu korrigieren.

    – Christian Gibbons

    4. Mai 2020 um 21:35 Uhr

  • @FrançoisAndrieux Okay, ich habe einige Änderungen am C++-Abschnitt der Antwort vorgenommen. Ich versuchte, es nicht zu hart in die Meinung fallen zu lassen.

    – Christian Gibbons

    4. Mai 2020 um 21:47 Uhr

1019310cookie-checkWarum müssen String-Literale (char*) in C++ Konstanten sein?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy