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.

War es hilfreich?

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.

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