Frage

Ich habe den folgenden Code bekommen:

#include <iostream>
using namespace std;
int main()
{
    char* a = "foo";
    char* b = "bar";
    a = b;
    cout << a << ", " << b << endl;
    return 0;
}

Dies kompiliert und arbeitet, das heißt. Druck bar, bar. Nun möchte Ich mag, dass zeigen, was hier geht ist nicht eine Zeichenfolge zu kopieren. Ich möchte b ändern und zeigen, dass a auch ändert. Ich kam mit diesem einfachen Code auf:

#include <iostream>
using namespace std;
int main()
{
    char* a = "foo";
    char* b = "bar";
    a = b;
    b[1] = 'u'; // ← just this line added
    cout << a << ", " << b << endl;
    return 0;
}

... aber es Segfaults. Warum? Das Interessante daran ist, dass die folgende Modifikation läuft ganz gut:

#include <iostream>
using namespace std;
int main()
{
    char* a = "foo";
    char b[] = "bar"; // ← declaration changed here
    a = b;
    b[1] = 'u';
    cout << a << ", " << b << endl;
    return 0;
}

Warum es nicht segfault die vorherige mögen? Ich glaube, ich bin einigen wichtigen Unterschied zwischen dem Zeiger-Stil fehle und die Array-String-Initialisierung.

War es hilfreich?

Lösung

Sie können keine String-Konstanten ändern, das ist, was Sie erhalten, wenn Sie den Zeiger-to-Literalsyntax wie in den ersten Codebeispiele verwenden.

Siehe auch diese Frage: Ist ein Stringliteral in c ++ in statischen Speicher erstellt? .

Andere Tipps

Wenn Sie schreiben diese:

char *b = "bar";

Der Compiler ordnet einen anonymen (namenlos) Speicherbereich die Stringliteral „bar“ zu speichern. Stringliterale können nicht geändert werden, so dass der Compiler (mit Hilfe des Linkers und Betriebssystem) stellt den Stringliteral in einem Teil des Speicherplatzes laufende Programm, das schreibgeschützt ist. Wenn Sie versuchen, es zu ändern, das Betriebssystem fängt sie und bewirkt, dass das Programm Fehler der Segmentierung.

(Ihr Code ist C ++, nicht C, aber das ist irrelevant für diese Frage.)

Wenn Sie schreiben:

char *foo = "bar";

Was tatsächlich passiert ist, dass die „Bar“ in dem Nur-Lese-Speichersegment gespeichert ist. Daher ist es unveränderlich. Sie erhalten eine segfault weil Sie versuchen, ein Nur-Lese-Segment zu ändern.

Sie können auch zeigen, dass ‚a‘ durch den Druck des Wertes des Zeigers geändert wurde.

#include <iostream>
using namespace std;
int main()
{
    char* a = "foo";
    char* b = "bar";
    a = b;

    cout << (void*)a << ", " << (void*)b << endl;
}

Dies druckt die Adresse, dass ‚a‘ und ‚b‘ Punkt, an.
Sie müssen ‚void *‘ zu werfen, weil der Operator << für ‚char *‘ Überlastung andere Zeiger aus der Zeichenfolge drucken die Adresse drucken.

In der Theorie ein Stringliteral sollte nicht in der Lage sein, zu einem char * zugeordnet wird, nur ein ‚const char *‘. Dann würde der Compiler Sie stoppen, bevor Sie seg schrieb Code Verwerfungen.

Dieser Unterschied ist vielleicht Compiler-spezifisch. Um Ihre Punkt Verwendung malloc zu zeigen, um den Puffer zuweisen, kopieren Sie die Zeichenfolge in diesen Puffer und vergessen Sie nicht, frei zu verwenden, wenn Sie nicht mehr die Zeichenfolge benötigen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top