Frage
Ich versuche immer zu vermeiden Stringliterale zurückzukehren, weil ich sie fürchten, nicht außerhalb der Funktion definiert. Aber ich bin nicht sicher, ob dies der Fall ist. Nehmen wir zum Beispiel diese Funktion:
const char *
return_a_string(void)
{
return "blah";
}
Ist der richtige Code? Es ist für mich zu arbeiten, aber vielleicht ist es funktioniert nur für meinen Compiler (gcc). Die Frage ist also, tun (string) Literale haben einen Umfang oder sind sie präsentieren / definiert die ganze Zeit.
Lösung
Dieser Code ist auf allen Plattformen in Ordnung. Der String wird in die binären als statischen Stringliteral zusammengestellt. Wenn Sie unter Windows zum Beispiel sind, können Sie sogar Ihre Exe mit Notepad öffnen und für die Zeichenfolge selbst suchen.
Da es sich um eine statische Stringliteral Umfang ist keine Rolle spielt.
String-Pooling:
Eine Sache zu achten ist, dass in einigen Fällen können identische Stringliterale „gepoolt“ werden, um Platz in der ausführbaren Datei zu speichern. In diesem Fall wörtliche jede Saite war, dass dasselbe die gleiche Speicheradresse haben könnte. Sie sollten nie davon ausgehen, dass es oder nicht, obwohl der Fall sein wird.
In den meisten Compiler können Sie festlegen, ob oder nicht statisch String-Pooling nutzen für Literale stirng.
Maximale Größe Stringliterale:
Einige Compiler haben eine maximale Größe für die Stringliteral. Zum Beispiel mit VC ++ ist dies etwa 2.048 Bytes.
ein Stringliteral Ändern gibt nicht definiertes Verhalten:
ein Stringliteral ändern sollte nie geschehen. Es hat ein nicht definiertes Verhalten.
char * sz = "this is a test";
sz[0] = 'T'; //<--- undefined results
Breit Stringliterale:
Alle oben gelten auch für breiten Stringliterale.
Beispiel: L: "Dies ist eine große Stringliteral";
Die C ++ Standard besagt: (Abschnitt lex.string)
1 Ein String ist eine Folge von Zeichen (wie definiert in lex.ccon ) in doppelten Anführungszeichen gesetzt, beginnend optional mit der Buchstaben L, wie in "..." oder L "...". Ein Zeichenfolgenliteral, die nicht beginnen mit L ist ein gewöhnlicher Stringliteral, auch als schmales bezeichnet Stringliteral. Ein gewöhnlicher Stringliteral hat Typ „Array von n const char“und statische Speicherdauer ( basic.stc ), wobei n die Größe der Zeichenfolge, wie unten definiert, und wird mit dem gegebenen initialisierten Figuren. Ein Zeichenfolgenliteral, die mit L wie L „asdf“ beginnt, ist eine breite Stringliteral. Eine breite Stringliteral hat Typ „Array von n const Wchar_t“und hat statische Lagerdauer, wobei n die Größe ist von die Zeichenfolge wie unten definiert, und wird mit dem gegebenen kenn initialisiert ters.
2, ob alle Stringliterale unterscheiden (dh, gespeichert in nicht überlappenden Objekten) ist die Implementierung definiert. Der Effekt von zu ändern versucht, eine Stringliteral ist nicht definiert.
Andere Tipps
Ich gebe Ihnen ein Beispiel, so dass Ihre Verwirrung etwas klar wird,
char *f()
{
char a[]="SUMIT";
return a;
}
das wird nicht funktionieren.
und
char *f()
{
char *a="SUMIT";
return a;
}
das funktioniert.
Grund: „SUMIT“ ist eine wörtliche, die eine globale Reichweite hat. während der Anordnung, die nur eine Folge von Zeichen { 'S', 'U', 'M', 'I', 'T '' \ 0' } ist hat eine begrenzte Reichweite und es verschwindet, sobald das Programm zurückgegeben wird.
Hope, das hilft
Dies gilt in C (oder C ++), wie andere erklärt haben.
Das einzige, was ich denken kann, zu achten, dass, wenn Sie DLLs verwenden, dann wird der Zeiger nicht gültig bleiben, wenn die DLL-Code enthält, entladen wird.
Die C (oder C ++) Standard nicht versteht oder zur Laufzeit aufgrund des Be- und Entladen Code nehmen, so alles, was das tut, wird die Implementierung definierte Konsequenzen: In diesem Fall ist die Folge, dass der Stringliteral, das ist angeblich statische Speicherdauer hat, erscheint aus der POV des anrufenden Code nicht für die gesamte Dauer des Programms bestehen bleiben.
Ja, das ist in Ordnung. Sie leben in einer globalen String-Tabelle.
Nein, Stringliterale nicht über Umfang, so dass Ihr Code ist garantiert auf allen Plattformen und Compiler zu arbeiten. Sie sind in Ihrem Programm der binären Bild gespeichert, so dass Sie sie immer zugreifen. Doch um sie zu schreiben versucht (durch die const
Wegwerfen) wird zu undefinierten Verhalten führen.
Sie kehren tatsächlich einen Zeiger auf die Null-terminierten String im Datenteil der ausführbaren Datei gespeichert, geladen ein Bereich, wenn Sie das Programm laden. Vermeiden Sie einfach die Zeichen, um zu versuchen und zu ändern, könnte es zu unvorhersehbaren Ergebnissen geben ...
Es ist wirklich wichtig, Kenntnis von den undefinierten Ergebnissen zu machen, die Brian erwähnt. Da Sie die Funktion als Rückgabe eines const char * Typ deklariert haben, sollten Sie in Ordnung sein, aber auf vielen Plattformen Stringliterale in einen Nur-Lese-Segment in der ausführbaren Datei (in der Regel das Textsegment) platziert und die Änderung von ihnen wird eine Zugriffsverletzung verursachen auf den meisten Plattformen.