18 Stimmen

Unterschied zwischen static const char* und const char*

Könnte jemand bitte den Unterschied erklären, wie die 2 folgenden Codeschnipsel behandelt werden? Sie kompilieren definitiv zu unterschiedlichem Assemblercode, aber ich versuche zu verstehen, wie sich der Code unterschiedlich verhalten könnte. Ich verstehe, dass String-Literale in den Nur-Lese-Speicher geworfen werden und effektiv statisch sind, aber wie unterscheidet sich das von der expliziten statischen unten?

struct Obj1
{
    void Foo()
    {
        const char* str( "hello" );
    }
};

y

struct Obj2
{
    void Foo()
    {
        static const char* str( "hello" );
    }
};

3 Stimmen

static const char tiene static vorher geschrieben const char

19voto

johannes Punkte 15447

Bei Ihrer statischen Version gibt es nur eine Variable, die irgendwo gespeichert wird, und jedes Mal, wenn die Funktion ausgeführt wird, wird genau dieselbe Variable verwendet. Auch bei rekursiven Aufrufen.

Die nicht-statische Version wird bei jedem Funktionsaufruf auf dem Stack gespeichert und nach jedem Aufruf zerstört.

Ihr Beispiel ist etwas kompliziert, was die eigentliche Arbeit des Compilers angeht, also lassen Sie uns zunächst einen einfacheren Fall betrachten:

void foo() {
    static long i = 4;
    --i;
    printf("%l\n", i);
}

Und dann ein Hauptartikel wie dieser:

int main() {
    foo();
    foo();
    return 0;
}

wird gedruckt

3
2

während bei

void foo() {
    long i = 4;
    --i;
    printf("%l\n", i);
}

es wird gedruckt

3
3

Jetzt mit Ihrem Beispiel haben Sie eine Konstante, so dass der Wert nicht geändert werden kann, so dass der Compiler könnte spielen einige Tricks, während es oft keine Auswirkungen auf den erzeugten Code hat, sondern dem Compiler hilft, Fehler zu erkennen. Und dann haben Sie einen Zeiger, und beachten Sie, dass die Statik Auswirkungen auf den Zeiger selbst hat, nicht auf den Wert, auf den er zeigt. Die Zeichenkette "Hallo" aus Ihrem Beispiel wird also höchstwahrscheinlich im .data-Segment Ihrer Binärdatei abgelegt, und zwar nur einmal und so lange, wie das Programm lebt, unabhängig von der statischen Sache.

11voto

Thomas Matthews Punkte 54757

Ich habe herausgefunden, dass einige Compiler die beiden unterschiedlich behandeln.

Die Version mit const char * kopiert Daten von einem schreibgeschützten Speicherort in eine Variable auf dem Stack.

Die Version mit static const char * verweist auf die Daten im Nur-Lese-Speicherort (es wird keine Kopie erstellt).

Ich habe diesen Unterschied entdeckt, als ich mit dem Debugger den Assembler-Code einer Funktion durchging. Ich schlage vor, entweder den Assemblercode auszudrucken oder mit einem Debugger auf Assemblersprachebene durchzugehen, um den genauen Unterschied zu finden Wahrheit .

10voto

sbi Punkte 211669

Eine lokale statische Variable ist das erste Mal initialisiert seine Definition angetroffen wird, aber nicht vernichtet wenn die Funktion beendet wird. Es ist also behält seinen Wert zwischen den Aufrufen der Funktion.

Im Falle eines const ist dies nicht sehr hilfreich - zumindest solange die Konstruktion des konstanten Wertes von der Leistung her genauso vernachlässigbar ist wie die Zuweisung einer Adresse. (Wenn die const Objekt kein konstanter Ausdruck ist oder die Erstellung des Ausdrucks erhebliche Ressourcen erfordert - wie in const Foo bar = foobar(); donde foobar() kann beträchtliche Zeit in Anspruch nehmen -, könnte der Unterschied wichtig werden.)

Es macht einen Unterschied, wenn Sie das Objekt per Referenz oder Zeiger zurückgeben wollen: Sie können keinen Verweis oder Zeiger auf ein lokales Objekt zurückgeben, es sei denn, es handelt sich um ein lokales statisches Objekt. ( Vielen Dank an Matthieu für diesen Hinweis. ) Wenn Sie dies verwenden möchten, müssen Sie jedoch bedenken, dass lokale Statiken von Natur aus thread-unsicher sind.

1 Stimmen

Ich denke, Sie sollten den Unterschied in der Lebensdauer hervorheben, Sie können einen Verweis/Zeiger auf die lokale statische zurückgeben, aber es ist undefiniert, dies mit einer klassischen Stack-Variable zu tun.

0 Stimmen

@Matthieu: Sie haben Recht, daran hatte ich nicht gedacht. Danke, ich werde das meiner Antwort hinzufügen.

1 Stimmen

Und ich bin froh, dass Sie das Thema "Einfädeln" erwähnt haben :) Die Leute vergessen oft, dass lokale statische Variablen mit globalen Variablen vergleichbar sind und unter all deren Problemen leiden.

2voto

JoeG Punkte 12744

Es gibt zwar einen technischen Unterschied, aber in Bezug auf die Verwendung und die Wirkung sind Ihre beiden Beispiele identisch.

Genauer gesagt, Ihre Nutzung der static Schlüsselwort gilt für den Zeiger auf das String-Literal,

I

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X