Ich weiß, dass ich wahrscheinlich mit dieser Frage gegen das tote Pferd ankämpfe, aber ich bin ein wenig verwirrt und habe es nicht geschafft, eine exakte Antwort auf SO oder Google zu finden (ich bin zuversichtlich, dass es stimmt - es gibt nur zu viele Informationen über C-Saiten zum Durchsehen). Außerdem habe ich C ++ getaggt, weil es mich interessiert, obwohl wir speziell über C-Style-Strings sprechen.
In dieser Situation:
%Vor%Ich hätte gedacht, dass "Hallo" und "Auf Wiedersehen" beide unveränderliche Zeichenfolgen sind, weil sie aus Zeichenfolgenliteralen kommen, die in ein Zeichen const * zerfallen sollten.
Ich habe gesehen, dass in diesem speziellen Fall die Änderung von "hallo" undefiniert wäre, während die Änderung von "tschüss" in Ordnung wäre, vorausgesetzt, Sie haben die Konstante aus dem b-Array entfernt.
Ich nehme an, dass der String im Fall von b veränderbar ist, weil er in einem benutzerdefinierten Array gespeichert ist.
Sind hallo und tschüss in diesem Fall anders? Ist in diesem Beispiel aus irgendeinem Grund kein String-Literal. Auch, wenn auf Wiedersehen kein String-Literal ist, kann ich annehmen, dass es nicht im globalen Speicher gehalten wird, und der einzige Verweis darauf nach der Kompilierzeit ist das, was in den Benutzer-Array-Zellen übrig ist?
Der erste erzeugt einen Zeiger, der auf das String-Literal "hello"
zeigt, das wahrscheinlich in nicht beschreibbarem Speicher im ausführbaren Bild des Programms gespeichert ist. Auch wenn dies nicht der Fall ist, dürfen Sie den Inhalt dieses Arrays nicht ändern.
Der zweite erzeugt ein automatisches Array 1 (auf dem Stack (normalerweise, aber das ist implementierungsdefiniert)) und initialisiert es mit der Zeichenkette "goodbye"
. Es ist äquivalent zu
Während also "goodbye"
unveränderlich ist, weil es ein String-Literal ist, das char const[8]
ist und in nicht beschreibbarem Speicher gespeichert ist, ist das Array b
ein automatisches 1 -Array, das unveränderlich ist, weil Sie haben es als const
markiert, aber Sie könnten const
aus der Variablendeklaration entfernen, um den Inhalt des Arrays veränderbar zu machen. Sie initialisieren nur den Inhalt des Arrays mit dem Inhalt des Arrays "goodbye"
.
Sie dürfen keine von beiden ändern, da beide const char[]
sind, aber die zweite könnte in char[]
geändert werden, während die erste nicht geändert werden konnte.
Siehe diese Antwort für weitere Informationen: Ссылка
1 Wie R. Martinho Fernandes in den Kommentaren darauf hingewiesen hat, könnte die Syntax T x[] = ...
auch ein statisches Array erzeugen (nicht automatisch, sondern statisch (im ausführbaren Bild normalerweise, aber das ist die Implementierung) ) wenn es sich um einen Namespace-Bereich handelt und ansonsten nur ein automatisches Array.
Ein String-Literal hat den Typ char const[N]
; natürlich kann ein Name dieses Typs in char const*
zerfallen.
Jetzt:
Ein char
-Array kann von einem String-Literal (8.5.2 / 1) initialisiert werden, und da Sie sonst keine Arrays kopieren oder zuweisen können, implementiert diese Initialisierung eine Kopie. Sie können mit dem neuen, veränderbaren Array tun, was immer Sie wollen.
Umgekehrt erhalten Sie beim Initialisieren eines Zeigers einen Zeiger, der das Ergebnis des Verfalls des unveränderlichen Array-Typs des Zeichenfolgenliterals ist.
%Vor%Hier gibt es kein neues Array. Kopieren Sie einfach einen Zeiger auf die vorhandenen, unveränderlichen Daten.
Sie sind anders. a
zeigt auf ein Zeichenfolgenliteral, das Sie nicht ändern können. % Co_de% ist jedoch ein Array von Zeichen, das mit der angegebenen Zeichenfolge initialisiert wird. Angenommen, die b
wurden entfernt, dann können Sie den Inhalt von const
ändern.
Ja, sie sind anders.
Es stimmt, dass die String-Literale selbst ( "hello"
und "goodbye"
) unveränderlich sind. Wenn Sie jedoch auf b
zugreifen, greifen Sie nicht auf Ihre ursprüngliche "goodbye"
zu. Der von Ihnen verwendete Code deklarierte ein vollständig unabhängiges Array b
, das nur mit einem String-Literal "goodbye"
initialisiert ist. Ihr 'b' ist völlig unabhängig vom ursprünglichen String-Literal "goodbye"
. Ihr b
ist eine Kopie dieses String-Literals. Der einzige Grund, warum Ihr 'b' unveränderlich ist, ist der const
, den Sie explizit in seiner Deklaration angegeben haben. Entferne das const
und dein b
wird perfekt veränderbar, wie jedes normale Array.
Wie für Ihr 'a' ist es ein Zeiger, der direkt auf das ursprüngliche String-Literal "hello"
zeigt. Es ist natürlich unveränderlich.
Beide Optionen sind unveränderlich, aber nicht, weil sie aus einem String-Literal erstellt wurden. Sie sind aufgrund des Schlüsselworts const
in den Variablendeklarationen unveränderlich.
Sie könnten auch char c[] = "string_c";
schreiben und eine veränderbare Kopie (namens c
) des Literals string_c
erstellen.
In Ihrem Beispiel über das Entfernen der Konstanten von b
, das unter bestimmten Umständen erscheinen kann, ist es immer noch illegal, was den Standard betrifft. Nur Objekte, die wirklich nicht-const sind, können mutiert sein.