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!
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!
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?
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.
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.
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
.
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.
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.