eine statische Variable in c

8

Hallo Ich studiere für meinen Test in C und ich bin auf eine Frage gestoßen, die ich nicht beantworten kann.

Ein Programmierer schrieb ein Programm, um die Anzahl der Benutzer zu zählen (Count.h, Count.c):

%Vor%

Und ein Tester, um es zu testen:

%Vor%

Überraschenderweise war die Ausgabe:

%Vor%

Ich kann nicht verstehen, warum der Zähler bei dieser Verwendung der statischen Variable nicht weiterkommt. Warum haben sie eine solche Eingabe erhalten?

Danke euch allen!

    
Asher Saban 03.10.2010, 17:34
quelle

7 Antworten

12

Denken Sie einfach daran, dass ".h-Dateien nicht existieren". Was passiert, ist, dass die .h-Dateien in den .c-Dateien enthalten sind und nur die .c-Dateien kompiliert (und miteinander verknüpft) werden.

In Ihrem Fall haben Sie 2 .c Dateien mit

%Vor%

Jedes counter ist spezifisch für die .c-Datei, in der es sich befindet. Das counter in CounterMain.c ist eine andere Variable als das counter in Counter.c.

Sie müssen eine einzelne Definition des Zählers haben. Sie können mehrere Deklarationen haben (normalerweise in .h-Dateien)

%Vor%

Ohhhhhhhhhhhhhhhhhh und da ist das static Ding. Benutze es nicht auf globaler Ebene!

    
pmg 03.10.2010, 17:41
quelle
14

In C ist der Bereich einer statischen Variable die Quelldatei, in der sie definiert ist.

Da Sie diesen Header in zwei separate .c-Dateien laden, erhält jede Datei eine eindeutige Variable. Das Inkrementieren von "Zähler" in einer Datei hat keinen Einfluss auf die "statische" Variable in der anderen Datei.

Einzelheiten finden Sie in dieser Beschreibung . Damit die Variable in mehreren Dateien sichtbar und freigegeben ist, muss sie als extern deklariert werden. Ansonsten:

  

Statische globale Variablen: Variablen, die auf der obersten Ebene einer Quelldatei (außerhalb beliebiger Funktionsdefinitionen) als statisch deklariert sind, sind in der gesamten Datei sichtbar ("Dateibereich").

Was ist hier der Fall?

    
Reed Copsey 03.10.2010 17:38
quelle
3

static int counter = 0;

Wenn eine Variable mit dem statischen Speicherklassenspezifizierer definiert wurde, hat die Variable ein interne Verknüpfung . Das heißt, Sie können counter innerhalb derselben Übersetzungseinheit verwenden, in der sie definiert ist.

>     
Prasoon Saurav 03.10.2010 17:42
quelle
3

Ein C-Programm wird erstellt, indem eine oder mehrere Übersetzungseinheiten miteinander kombiniert werden, um ein Programm zu erstellen.

Eine Übersetzungseinheit ist tatsächlich eine vorverarbeitete Quelldatei. Es enthält alle Header- und Quellendateien, die in #include Direktiven angegeben sind, und schließt alles aus, was von #if oder ähnlichen Direktiven ausgeschlossen wurde.

Wenn eine Variable im Dateibereich static deklariert wird, wird der Variablenname interne Verknüpfung angegeben. Dies bedeutet, dass sich der Name auf ein Objekt bezieht, das lokal für die Übersetzungseinheit ist, in der es angezeigt wird. Wenn der Name in einer anderen Übersetzungseinheit verwendet wird, kann er nicht auf das Objekt in dieser Übersetzungseinheit verweisen, er muss sich auf ein anderes Objekt beziehen.

[Im Gegensatz dazu bezieht sich ein Name mit externer Verknüpfung auf dasselbe Objekt, unabhängig von der Übersetzungseinheit, in der der Name verwendet wird.]

%Vor%

Wenn Sie eine solche Deklaration in eine Header-Datei schreiben, bedeutet dies, dass jede Übersetzungseinheit, die die Header-Datei enthält, ihr eigenes eindeutiges Objekt namens counter hat, das sich von jedem Objekt namens counter in jeder anderen Übersetzung unterscheidet Einheit.

In Ihrem Fall gibt es ein counter in der Übersetzungseinheit, generiert aus CounterMain.c und ein separates in der Übersetzungseinheit erzeugt aus Count.c . Der Wert in Count.c wird niemals erhöht, sondern von getUserNum() zurückgegeben, der Wert in CounterMain.c wird in main erhöht, aber nirgendwo anders verwendet.

    
Charles Bailey 03.10.2010 18:25
quelle
2

Das Schlüsselwort static bedeutet, dass die Funktion oder Variable, wenn sie zur Qualifizierung von Funktionen oder globalen Variablen verwendet wird, internal linkage haben sollte, was bedeutet, dass sie nicht als globales Symbol sichtbar sein sollte. Daher wird jede Kompilierungseinheit, die Counter.h enthält, eine eigene lokale Kopie von counter haben, die nicht mit anderen kollidiert.

In diesem Fall haben Counter.c und CounterMain.c unterschiedliche Variablen count , was zu dem führt, was Sie beschrieben haben.

Die Lösung besteht darin, die Definition von counter in Counter.h in eine Deklaration zu ändern:
extern int counter;
und um die Definition in Counter.c zu setzen:
int counter = 0;

Danach sollten CounterMain und alle anderen Kompilierungseinheiten einschließlich Counter.h auf die einzelne Instanz counter zugreifen können, aber Sie können sich auch information hiding gönnen und nur über Funktionen in Counter darauf zugreifen in einem saubereren interface .

    
aib 03.10.2010 17:41
quelle
1

Dies liegt daran, dass die statische Variable im Header deklariert ist. In C existieren statische Variablen nur in der .c -Datei, in der sie deklariert sind. Da Ihr .h in zwei unterschiedlichen .c-Dateien enthalten ist ( #include directions kann nur als Copy-Paste-Operation angesehen werden), werden zwei statische Variablen mit dem Namen counter erstellt, eine in jeder Datei. Ihre Testdatei inkrementiert ihre lokale counter -Variable, aber die von getUsersNum zurückgegebene stammt aus einer anderen C-Datei und ist vollständig unabhängig.

Was versucht wird, ist der Zugriff auf eine statische Variable aus einer anderen Datei als der, in der sie deklariert wurde. Du solltest wissen, dass es nicht (direkt) möglich ist. Um den richtigen Zähler zu erhöhen, benötigen Sie eine Funktion, die auf der counter -Variable von Counter.c ausgeführt wird.

    
zneak 03.10.2010 17:41
quelle
1

Eine static Variable ist nur in der Datei verfügbar, in der sie definiert ist. In diesem Beispiel haben Counter.c und CounterMain.c beide ihre eigene Variable counter .

Wenn ++counter ausgeführt wird, aktualisiert dies die in CounterMain.c deklarierte Variable. Wenn jedoch getUsersNum() aufgerufen wird, gibt dies den Wert der counter -Variablen von Counter.c zurück, die nicht inkrementiert wurden.

Wenn Sie getUsersNum() in counter ändern, sehen Sie, dass die in counter deklarierte Variable CounterMain.c inkrementiert wurde.

    
Richard Fearn 03.10.2010 17:40
quelle

Tags und Links