Wann sollte das statische Schlüsselwort vor globalen Variablen verwendet werden?

73

Kann jemand erklären, wann Sie das statische Schlüsselwort vor globalen Variablen oder Konstanten verwenden sollen, die in Header-Dateien definiert sind?

Nehmen wir zum Beispiel an, ich habe eine Header-Datei mit der Zeile:

const float kGameSpriteWidth = 12.0f;

Sollte dies staticvor constoder nicht haben? Was sind einige Best Practices für die Verwendung static?

Matt
quelle
Beachten Sie, dass in C ++ alle Variablen mit globalem Namespace- Qualifikation staticimpliziert sind (dh staticstandardmäßig) const, obwohl ich empfehlen würde, sie als staticunabhängig zu qualifizieren, damit die Absicht klar wird.
abc
Siehe auch Wie kann ich externVariablen zwischen Quelldateien freigeben? Die Antworten dort erklären, wie Werte geteilt werden - und ein wesentlicher Teil von ist die Verwendung eines Headers , um gemeinsam genutzte Variablen zu deklarieren (aber nicht zu definieren). Wenn Sie keinen Header zum Einfügen der Deklaration haben, sollte die Variablendefinition statisch sein. Wenn Sie einen Header dafür haben, fügen Sie den Header sowohl dort ein, wo die Variable definiert ist (das ist nur eine Quelldatei) als auch dort, wo sie verwendet wird (möglicherweise viele Quelldateien).
Jonathan Leffler

Antworten:

55

staticrendert die Variable lokal in der Datei, was im Allgemeinen eine gute Sache ist, siehe zum Beispiel diesen Wikipedia-Eintrag .

Dirk Eddelbuettel
quelle
15
Ich denke nicht, dass dies mit "Dateien" zu tun hat, sondern mit "Kompilierungsmodulen".
AraK
1
Wenn die Variable nicht vorhanden externist, kann von außerhalb der CDatei nicht darauf zugegriffen werden. Was bringt es dann, es als statisch zu definieren?
Alex
@alex Eine sehr gute Frage. Standardmäßig sind globale Variablen extern, es wird jedoch empfohlen, sie trotzdem als solche zu kennzeichnen.
Austin Salgat
113

Sie sollten nicht definieren globale Variablen in Header - Dateien. Sie sollten sie in der .c-Quelldatei definieren.

  • Wenn eine globale Variable nur in einer .c-Datei sichtbar sein soll, sollten Sie sie als statisch deklarieren.

  • Wenn eine globale Variable für mehrere .c-Dateien verwendet werden soll, sollten Sie sie nicht als statisch deklarieren. Stattdessen sollten Sie es extern in der Header-Datei deklarieren, die in allen .c-Dateien enthalten ist, die es benötigen.

Beispiel:

  • Beispiel.h

    extern int global_foo;
    
  • foo.c

    #include "example.h"
    
    int global_foo = 0;
    static int local_foo = 0;
    
    int foo_function()
    {
       /* sees: global_foo and local_foo
          cannot see: local_bar  */
       return 0;
    }
    
  • bar.c

    #include "example.h"
    
    static int local_bar = 0;
    static int local_foo = 0;
    
    int bar_function()
    {
        /* sees: global_foo, local_bar */
        /* sees also local_foo, but it's not the same local_foo as in foo.c
           it's another variable which happen to have the same name.
           this function cannot access local_foo defined in foo.c
        */
        return 0;
    }
    
Tomek Szpakowicz
quelle
2
Ich denke, Sie haben den Punkt verpasst. Dies ist ein const float. Es ist nichts Falsches daran, eine statische const in einer Header-Datei zu definieren und in jeder Übersetzungseinheit eine andere Kopie davon zu haben. Aber die meisten Leute würden einfach ein #define für ein Literal verwenden.
Steve Jessop
6
Die Frage war: "Kann jemand erklären, wann Sie das statische Schlüsselwort vor globalen Variablen oder Konstanten verwenden sollen, die in Header-Dateien definiert sind?" Da OP Anfänger zu sein scheint, habe ich einfach die grundlegendste Regel zum Definieren globaler Variablen in C angegeben. Wie Sie selbst bemerkt haben, können Sie sich normalerweise keinen Schaden zufügen, wenn Sie globale _const_s in der Header-Datei verwenden (in C ist dies in C ++ nicht so einfach ).
Tomek Szpakowicz
Immerhin ist es nur die Durchsetzung des Compilers. Und schließlich ist es nichts als der Wille des Menschen ...
smwikipedia
1
Ist die Aufnahme von example.h in foo.c erforderlich?
hammadian
@hammadian Es ist in diesem Fall nicht notwendig. Trotzdem ist es eine gute Idee, es aufzunehmen. Der Compiler kann Diskrepanzen zwischen Deklarationen in der h-Datei und Definitionen in der c-Datei erkennen.
Tomek Szpakowicz
27

Ja, statisch verwenden

Verwenden Sie in .cDateien immer statisch , es sei denn, Sie müssen auf das Objekt eines anderen .cModuls verweisen .

Verwenden .hSie niemals statisch in Dateien, da Sie jedes Mal ein anderes Objekt erstellen, wenn es enthalten ist.

DigitalRoss
quelle
Der Linker kann nicht erkennen, dass es sich um Konstanten handelt, und alle verschiedenen Objekte optimieren.
Trevor Hickey
Sie sind jedoch keine Konstanten, und es ist wichtig, dass der Linker private Objekte nicht versehentlich zusammenführt, nur weil sie denselben Namen haben. Linker haben überhaupt keine Informationen auf hoher Ebene, sie befassen sich nur mit Symbolen, Bitfolgen, Leerzeichen und Referenzen. Konstanten sind für Linker überhaupt nicht sichtbar, sie wirken sich nur auf den generierten Code während der Kompilierung aus.
DigitalRoss
6
Eine andere Möglichkeit, dies zu sagen, ist: Der gesamte Sinn von staticbesteht darin, zuzulassen , dass derselbe Name zwei verschiedene Objekte in zwei verschiedenen Modulen sind.
DigitalRoss
8

Faustregel für Header-Dateien:

  • extern int foo;Deklarieren Sie die Variable als und fügen Sie eine entsprechende Initialisierung in eine einzelne Quelldatei ein, um einen veränderbaren Wert zu erhalten, der von den Übersetzungseinheiten gemeinsam genutzt wird
  • Verwenden Sie static const int foo = 42;diese Option, um eine Konstante zu erhalten, die eingefügt werden kann
Christoph
quelle
6

Das statische Schlüsselwort wird in C verwendet, um die Sichtbarkeit einer Funktion oder Variablen auf ihre Übersetzungseinheit zu beschränken . Die Übersetzungseinheit ist die ultimative Eingabe für einen C-Compiler, aus dem eine Objektdatei generiert wird.

Überprüfen Sie dies: Verknüpfung | Übersetzungseinheit

pj
quelle
5

static vor einer globalen Variablen bedeutet, dass auf diese Variable von außerhalb des Kompilierungsmoduls, in dem sie definiert ist, nicht zugegriffen werden kann.

Stellen Sie sich beispielsweise vor, Sie möchten auf eine Variable in einem anderen Modul zugreifen:

foo.c

int var; // a global variable that can be accessed from another module
// static int var; means that var is local to the module only.
...

bar.c

extern int var; // use the variable in foo.c
...

Wenn Sie sich jetzt varals statisch deklarieren , können Sie nur von dem Modul aus darauf zugreifen, in das foo.ckompiliert wurde.

Beachten Sie, dass ein Modul die aktuelle Quelldatei sowie alle enthaltenen Dateien ist. Das heißt, Sie müssen diese Dateien separat kompilieren und dann miteinander verknüpfen.

AraK
quelle
-1

Der richtige Mechanismus für C ++ in anonymen Namespaces. Wenn Sie etwas möchten, das lokal für Ihre Datei ist, sollten Sie einen anonymen Namespace anstelle des statischen Modifikators verwenden.

rmn
quelle
Ich denke, diese Antwort ist schlecht formuliert, zu prägnant und nicht thematisch (obwohl das OP dies nicht spezifiziert, ist die Frage mit C und nicht mit C ++ gekennzeichnet).
p4010
-2

Globale statische Variablen werden im Gegensatz zur automatischen Kompilierungszeit initialisiert

Captain Comic
quelle