Ich habe das Wort statican verschiedenen Stellen im C-Code gesehen. Ist dies wie eine statische Funktion / Klasse in C # (wo die Implementierung von mehreren Objekten gemeinsam genutzt wird)?
Was ist der Grund, "in einem C-Programm" am Ende des Titels @Lundin zu entfernen? Bei Vorhandensein von Tag c ist es etwas redundant , aber ich kann die Kategorisierung schneller sehen, ohne die Tags zu überprüfen. Diese Redundanz ist sehr komfortabel, wenn ich die Frage aus einer Richtung erreiche, die möglicherweise auch Fragen zu anderen Sprachen enthält, z. B. statische oder Google-Suche.
Palec
5
@Palec Es gibt eine SO-Richtlinie, nach der Elemente, die in der Tag-Liste vorhanden sind, im Titel redundant sind. Die Site hängt C automatisch an die eigentliche Website an. Ein Google für "C static" gibt diese Antwort als Top-Hit. Der Grund, warum dies geändert wurde, ist, dass diese Frage jetzt Teil der SOQ-Sprach-FAQ ist und alle hinzugefügten Beiträge ein wenig aufpoliert werden.
Lundin
1
@Lundin Ich bevorzuge es, "C" im Titel zu behalten, da SO nur ein Tag an den Titel anfügt (das häufigste?). Was ist, wenn eines Tages "Syntax" mehr Fragen als C erreicht (da es sich um eine sprachübergreifende Sache handelt)? Ich würde lieber das explizite Verhalten verwenden :-) Bearbeiten: ah, aber es gibt eine Meta-Frage, die etwas anderes sagt: meta.stackexchange.com/questions/19190/…
Eine statische Variable innerhalb einer Funktion behält ihren Wert zwischen Aufrufen bei.
Eine statische globale Variable oder eine Funktion wird nur in der Datei "gesehen", in der sie deklariert ist
(1) ist das fremdere Thema, wenn Sie ein Neuling sind. Hier ist ein Beispiel:
#include<stdio.h>void foo(){int a =10;staticint sa =10;
a +=5;
sa +=5;
printf("a = %d, sa = %d\n", a, sa);}int main(){int i;for(i =0; i <10;++i)
foo();}
Dies druckt:
a =15, sa =15
a =15, sa =20
a =15, sa =25
a =15, sa =30
a =15, sa =35
a =15, sa =40
a =15, sa =45
a =15, sa =50
a =15, sa =55
a =15, sa =60
Dies ist nützlich in Fällen, in denen eine Funktion einen bestimmten Status zwischen Aufrufen beibehalten muss und Sie keine globalen Variablen verwenden möchten. Beachten Sie jedoch, dass diese Funktion sehr sparsam verwendet werden sollte. Dadurch ist Ihr Code nicht threadsicher und schwerer zu verstehen.
(2) Wird häufig als "Zugangskontroll" -Funktion verwendet. Wenn Sie eine .c-Datei haben, die einige Funktionen implementiert, werden Benutzern normalerweise nur einige "öffentliche" Funktionen zur Verfügung gestellt. Der Rest seiner Funktionen sollte so ausgeführt werden static, dass der Benutzer nicht darauf zugreifen kann. Dies ist eine Kapselung, eine gute Praxis.
In der Programmiersprache C wird static mit globalen Variablen und Funktionen verwendet, um deren Gültigkeitsbereich auf die enthaltene Datei festzulegen. In lokalen Variablen wird statisch verwendet, um die Variable im statisch zugewiesenen Speicher anstelle des automatisch zugewiesenen Speichers zu speichern. Während die Sprache die Implementierung eines der beiden Speichertypen nicht vorschreibt, wird der statisch zugewiesene Speicher zur Kompilierungszeit normalerweise im Datensegment des Programms reserviert, während der automatisch zugewiesene Speicher normalerweise als vorübergehender Aufrufstapel implementiert wird.
Und um Ihre zweite Frage zu beantworten, ist es nicht wie in C #.
In C ++ wird es jedoch staticauch verwendet, um Klassenattribute (die von allen Objekten derselben Klasse gemeinsam genutzt werden) und Methoden zu definieren. In C gibt es keine Klassen, daher ist diese Funktion irrelevant.
Pax, das OP weiß nichts über Statik, also schlagen Sie vor, ihn in den Unterschied zwischen Kompilierungseinheiten und Dateien zu stürzen? :-)
Eli Bendersky
138
Eine Kompilierungseinheit ist eine einzelne Datei, die der Compiler sieht. Ihre .c-Datei kann andere .c-Dateien enthalten, aber nachdem der Präprozessor die Includes aussortiert hat, sieht der Compiler schließlich nur eine einzige "Kompilierungseinheit".
Eli Bendersky
81
@robUK: Der Compiler kennt nicht einmal die .h-Dateien - diese werden im Vorprozessor zu den .c-Dateien zusammengefasst. Ja, Sie können also sagen, dass die .c-Datei mit allen darin enthaltenen Headern eine einzige Kompilierungseinheit ist.
Eli Bendersky
6
@ TonyD vielleicht ist es verwirrend, aber so funktioniert die Kompilierung. Es kann normalerweise eine .coder mehrere Header-Dateien sein, aber der Teufel befindet sich immer in dem, was nicht typisch ist.
Peterph
7
@TonyD Der Compiler kompiliert. Der Präprozessor führt die Vorverarbeitung durch. Das Aufrufen der Toolchain "Compiler" ändert nichts daran, was es ist oder was es tut.
Miles Rout
231
Es gibt eine weitere Verwendung, die hier nicht behandelt wird, und zwar als Teil einer Array-Typdeklaration als Argument für eine Funktion:
int someFunction(char arg[static10]){...}
In diesem Zusammenhang gibt dies an, dass an diese Funktion übergebene Argumente ein Array vom Typ charmit mindestens 10 Elementen sein müssen. Für weitere Informationen siehe meine Frage hier .
Ich dachte nicht, dass C Array-Argumente hat? Linus Torvalds schimpft wütend über Leute, die dies tun.
Suprjami
13
@jamieb: C nicht über Array - Argumente, aber diese spezifische Syntax bedeutet , dass die Funktion erwartet arg[0]durch arg[9]Werte zu haben (was bedeutet auch , dass die Funktion nicht einen Null - Zeiger nicht akzeptiert). Compiler könnten diese Informationen irgendwie zur Optimierung verwenden, und statische Analysatoren können diese Informationen verwenden, um sicherzustellen, dass der Funktion niemals ein Nullzeiger zugewiesen wird (oder, falls dies erkennbar ist, ein Array mit weniger Elementen als angegeben).
Dreamlax
19
@Qix - Dies war eine neue überladene Bedeutung, die staticin C99 angegeben wurde. Es ist mehr als anderthalb Jahrzehnte alt, aber nicht alle Compiler-Autoren haben alle C99-Funktionen übernommen - daher ist C99 insgesamt weitgehend unbekannt.
Happy Green Kid Nickerchen
@suprjami Ich bin mir nicht 100% sicher, was Sie unter "Array-Argumenten" verstehen, aber wenn Sie meinen int arr[n];, dann ist das ein VLA (Array variabler Länge) , das in C99 hinzugefügt wurde. Ist es das, was du meintest?
RastaJedi
170
Kurze Antwort ... es kommt darauf an.
Statisch definierte lokale Variablen verlieren zwischen Funktionsaufrufen nicht ihren Wert. Mit anderen Worten, es handelt sich um globale Variablen, die sich jedoch auf die lokale Funktion beschränken, in der sie definiert sind.
Statische globale Variablen sind außerhalb der C-Datei, in der sie definiert sind, nicht sichtbar.
Statische Funktionen sind außerhalb der C-Datei, in der sie definiert sind, nicht sichtbar.
Bedeutet "statische Funktion" und "private Funktion" dasselbe? In ähnlicher Weise sind "statische globale Variablen" und "private globale Variablen" dasselbe?
user1599964
40
Hier geht es um C. Es gibt keine privaten / öffentlichen in C.
Chris
19
@ user1599964 Obwohl es privatein C kein gibt, ist Ihre Analogie gut: statisch macht die Dinge für eine bestimmte Datei "privat". Und Dateien in C werden häufig Klassen in C ++ zugeordnet.
Ciro Santilli 法轮功 病毒 审查 六四 事件 法轮功
67
Beispiel für einen Variablenbereich mit mehreren Dateien
Hier zeige ich, wie sich statisch auf den Umfang der Funktionsdefinitionen in mehreren Dateien auswirkt.
ac
#include<stdio.h>/*
Undefined behavior: already defined in main.
Binutils 2.24 gives an error and refuses to link.
/programming/27667277/why-does-borland-compile-with-multiple-definitions-of-same-object-in-different-c
*//*int i = 0;*//* Works in GCC as an extension: https://stackoverflow.com/a/3692486/895245 *//*int i;*//* OK: extern. Will use the one in main. */externint i;/* OK: only visible to this file. */staticint si =0;void a(){
i++;
si++;
puts("a()");
printf("i = %d\n", i);
printf("si = %d\n", si);
puts("");}
m()
i =1
si =1
m()
i =2
si =2
a()
i =3
si =1
a()
i =4
si =2
Deutung
Es gibt zwei separate Variablen für si , eine für jede Datei
Es gibt eine einzige gemeinsam genutzte Variable für i
Wie üblich, je kleiner der Bereich, desto besser. Deklarieren Sie daher immer Variablen static wenn Sie können.
In der C-Programmierung werden Dateien häufig zur Darstellung von "Klassen" verwendet, und staticVariablen repräsentieren private statische Mitglieder der Klasse.
Was Standards dazu sagen
C99 N1256 Entwurf 6.7.1 "Speicherklassenspezifizierer" besagt diesstatic ein "Speicherklassenspezifizierer" ist.
6.2.2 / 3 "Verknüpfungen von Kennungen" staticimpliziert internal linkage:
Wenn die Deklaration eines Dateibereichsbezeichners für ein Objekt oder eine Funktion den statischen Speicherklassenspezifizierer enthält, ist der Bezeichner intern verknüpft.
und 6.2.2 / 2 sagt, dass internal linkagesich das wie in unserem Beispiel verhält:
In dem Satz von Übersetzungseinheiten und Bibliotheken, die ein gesamtes Programm bilden, bezeichnet jede Deklaration eines bestimmten Bezeichners mit externer Verknüpfung dasselbe Objekt oder dieselbe Funktion. Innerhalb einer Übersetzungseinheit bezeichnet jede Deklaration eines Bezeichners mit interner Verknüpfung dasselbe Objekt oder dieselbe Funktion.
Dabei ist "Übersetzungseinheit eine Quelldatei nach der Vorverarbeitung.
Wie implementiert GCC es für ELF (Linux)?
Mit der STB_LOCALBindung.
Wenn wir kompilieren:
int i =0;staticint si =0;
und zerlegen Sie die Symboltabelle mit:
readelf -s main.o
Die Ausgabe enthält:
Num:ValueSizeTypeBindVisNdxName5:00000000000000044 OBJECT LOCAL DEFAULT 4 si
10:00000000000000004 OBJECT GLOBAL DEFAULT 4 i
Die Bindung ist also der einzige signifikante Unterschied zwischen ihnen. Valueist nur ihr Versatz in den .bssAbschnitt, also erwarten wir, dass es anders ist.
STB_LOCAL Lokale Symbole sind außerhalb der Objektdatei mit ihrer Definition nicht sichtbar. Lokale Symbole mit demselben Namen können in mehreren Dateien vorhanden sein, ohne sich gegenseitig zu stören
Das macht es zu einer perfekten Wahl für die Darstellung static.
Variablen ohne statische Aufladung sind STB_GLOBALund die Spezifikation sagt:
Wenn der Link-Editor mehrere verschiebbare Objektdateien kombiniert, sind nicht mehrere Definitionen von STB_GLOBAL-Symbolen mit demselben Namen zulässig.
Dies stimmt mit den Verknüpfungsfehlern bei mehreren nicht statischen Definitionen überein.
Wenn wir die Optimierung mit ankurbeln -O3, wird das siSymbol vollständig aus der Symboltabelle entfernt: Es kann sowieso nicht von außen verwendet werden. TODO warum statische Variablen überhaupt in der Symboltabelle belassen, wenn keine Optimierung erfolgt? Können sie für irgendetwas verwendet werden? Vielleicht zum Debuggen.
Die Funktion würde 1, 2, 3 usw. zurückgeben. --- Die Variable befindet sich nicht auf dem Stapel.
ac:
staticint foo(){}
Dies bedeutet, dass diese Funktion nur in dieser Datei Gültigkeitsbereich hat. AC und bc können also unterschiedliche foo()s haben, und foo ist keinen gemeinsam genutzten Objekten ausgesetzt. Wenn Sie also foo in ac definiert haben, können Sie nicht von b.coder von anderen Orten darauf zugreifen .
In den meisten C-Bibliotheken sind alle "privaten" Funktionen statisch und die meisten "öffentlichen" nicht.
+1 für die Erwähnung von x nicht auf Stapel oder Haufen. Es befindet sich im statischen Speicherbereich.
Gob00st
1
@ Gob00st statischer Speicherplatz? Sie meinten "Datensegment" ...?
Yousha Aleayoub
24
Die Leute sagen immer wieder, dass 'statisch' in C zwei Bedeutungen hat. Ich biete eine alternative Sichtweise an, die ihm eine einzige Bedeutung gibt:
Das Anwenden von 'statisch' auf ein Element erzwingt, dass dieses Element zwei Eigenschaften hat: (a) Es ist außerhalb des aktuellen Bereichs nicht sichtbar; (b) Es ist hartnäckig.
Der Grund, warum es zwei Bedeutungen zu haben scheint, ist, dass in C jedes Element, auf das 'statisch' angewendet werden kann, bereits eine dieser beiden Eigenschaften hat , so dass es den Anschein hat, als ob diese bestimmte Verwendung nur die andere betrifft.
Betrachten Sie beispielsweise Variablen. Variablen, die außerhalb von Funktionen deklariert wurden, haben bereits eine Persistenz (im Datensegment). Wenn Sie also 'static' anwenden, können sie nur außerhalb des aktuellen Bereichs (Kompilierungseinheit) nicht sichtbar gemacht werden. Im Gegensatz dazu sind Variablen, die innerhalb von Funktionen deklariert wurden, bereits außerhalb des aktuellen Bereichs (Funktion) nicht sichtbar, sodass die Anwendung von 'statisch' sie nur dauerhaft machen kann.
Das Anwenden von 'statisch' auf Funktionen ist wie das Anwenden auf globale Variablen - Code ist notwendigerweise persistent (zumindest innerhalb der Sprache), sodass nur die Sichtbarkeit geändert werden kann.
HINWEIS: Diese Kommentare gelten nur für C. In C ++ gibt das Anwenden von 'static' auf Klassenmethoden dem Schlüsselwort eine andere Bedeutung. Ähnliches gilt für die C99-Array-Argument-Erweiterung.
Ihr (a) ist bestenfalls überflüssig. Außerhalb ihres Gültigkeitsbereichs ist keinerlei Variable sichtbar. Das ist einfach die Definition des Umfangs. Was Sie meinen, wird im C-Standard als Verknüpfung bezeichnet . staticgibt eine interne Verknüpfung zu einem Bezeichner.
Jens
16
Aus Wikipedia:
In der Programmiersprache C wird static mit globalen Variablen und Funktionen verwendet, um deren Gültigkeitsbereich auf die enthaltene Datei festzulegen. In lokalen Variablen wird statisch verwendet, um die Variable im statisch zugewiesenen Speicher anstelle des automatisch zugewiesenen Speichers zu speichern. Während die Sprache die Implementierung eines der beiden Speichertypen nicht vorschreibt, wird der statisch zugewiesene Speicher zur Kompilierungszeit normalerweise im Datensegment des Programms reserviert, während der automatisch zugewiesene Speicher normalerweise als vorübergehender Aufrufstapel implementiert wird.
static bedeutet verschiedene Dinge in verschiedenen Kontexten.
Sie können eine statische Variable in einer C-Funktion deklarieren. Diese Variable ist nur in der Funktion sichtbar, verhält sich jedoch insofern wie eine globale, als sie nur einmal initialisiert wird und ihren Wert beibehält. In diesem Beispiel wird bei jedem Anruf foo()eine zunehmende Zahl gedruckt. Die statische Variable wird nur einmal initialisiert.
void foo (){staticint i =0;
printf("%d", i); i++}
Eine andere Verwendung von statisch ist, wenn Sie eine Funktion oder eine globale Variable in einer .c-Datei implementieren, deren Symbol jedoch nicht außerhalb der .objvon der Datei generierten sichtbar sein soll . z.B
Wenn Sie eine Variable in einer statischen Funktion deklarieren, wird ihr Wert nicht im Funktionsaufrufstapel gespeichert und ist weiterhin verfügbar, wenn Sie die Funktion erneut aufrufen.
Wenn Sie eine globale Variable als statisch deklarieren, wird ihr Gültigkeitsbereich auf die Datei beschränkt, in der Sie sie deklariert haben. Dies ist etwas sicherer als ein reguläres globales Programm, das im gesamten Programm gelesen und geändert werden kann.
Ich hasse es, eine alte Frage zu beantworten, aber ich glaube, niemand hat erwähnt, wie K & R sie in Abschnitt A4.1 von "The C Programming Language" erklärt.
Kurz gesagt, das Wort statisch wird mit zwei Bedeutungen verwendet:
Statisch ist eine der beiden Speicherklassen (die andere ist automatisch). Ein statisches Objekt behält seinen Wert zwischen Aufrufen. Die außerhalb aller Blöcke deklarierten Objekte sind immer statisch und können nicht automatisch erstellt werden.
Wenn das staticSchlüsselwort (wobei der Schwerpunkt darauf liegt, dass es im Code als Schlüsselwort verwendet wird) mit einer Deklaration verwendet wird, wird das Objekt intern verknüpft, sodass es nur innerhalb dieser Übersetzungseinheit verwendet werden kann. Wenn das Schlüsselwort jedoch in einer Funktion verwendet wird, ändert es die Speicherklasse des Objekts (das Objekt wäre ohnehin nur in dieser Funktion sichtbar). Das Gegenteil von statisch ist das externSchlüsselwort, das eine externe Verknüpfung eines Objekts ergibt.
Peter Van Der Linden gibt diese beiden Bedeutungen in "Expert C Programming" an:
Behält innerhalb einer Funktion ihren Wert zwischen Aufrufen bei.
Es gibt eine dritte Speicherklasse, Register . Einige Leute plädieren auch für eine vierte Speicherklasse, die für den von malloc und Freunden zurückgegebenen Speicher zugewiesen wurde.
Jens
@Jens 'register' ist nur ein Hinweis für den Compiler; Der Registerspeicher kann nicht aus der C-Quelle heraus erzwungen werden. Ich würde es also nicht als Speicherklasse betrachten.
GermanNerd
1
@GermanNerd Ich befürchte, dass der ISO C-Standard Ihrer Ansicht nicht entspricht, da er eindeutig registereinen Speicherklassenspezifizierer darstellt (C99 6.7.1 Speicherklassenspezifizierer). Und es ist mehr als nur ein Hinweis: Sie können beispielsweise den Adressoperator nicht &auf ein Objekt mit Speicherklasse anwenden, registerunabhängig davon, ob der Compiler ein Register zuweist oder nicht.
Jens
@Jens Danke, dass du mich an & erinnert hast. Ich hätte vielleicht zu viel C ++ gemacht ..... Wie auch immer, während 'register' ein Speicherklassenspezifizierer ist, wird der Compiler in Wirklichkeit wahrscheinlich den gleichen Maschinencode für den (nutzlosen) 'auto'-Spezifizierer wie für das' register 'erstellen 'Spezifizierer. Das einzige, was noch übrig bleibt, ist die Einschränkung auf Quellcode-Ebene, keine Adresse annehmen zu können. Übrigens hat mich diese kleine Diskussion dazu gebracht, einen Fehler in Netbeans zu finden. Seit meinem letzten Update wird standardmäßig die g ++ - Toolkette für neue C-Projekte verwendet!
GermanNerd
6
In C hat statisch je nach Anwendungsbereich zwei Bedeutungen. Wenn im globalen Bereich ein Objekt auf Dateiebene deklariert wird, bedeutet dies, dass dieses Objekt nur in dieser Datei sichtbar ist.
In jedem anderen Bereich wird ein Objekt deklariert, das seinen Wert zwischen den verschiedenen Zeitpunkten beibehält, zu denen der bestimmte Bereich eingegeben wird. Wenn beispielsweise ein int innerhalb einer Prozedur gelöscht wird:
void procedure(void){staticint i =0;
i++;}
Der Wert von 'i' wird beim ersten Aufruf der Prozedur auf Null initialisiert, und der Wert bleibt bei jedem weiteren Aufruf der Prozedur erhalten. Wenn 'i' gedruckt würde, würde eine Folge von 0, 1, 2, 3, ... ausgegeben.
Es ist wichtig zu beachten, dass statische Variablen in Funktionen beim ersten Eintrag in diese Funktion initialisiert werden und auch nach Beendigung ihres Aufrufs bestehen bleiben. Bei rekursiven Funktionen wird die statische Variable nur einmal initialisiert und bleibt auch bei allen rekursiven Aufrufen und auch nach Beendigung des Funktionsaufrufs bestehen.
Wenn die Variable außerhalb einer Funktion erstellt wurde, bedeutet dies, dass der Programmierer die Variable nur in der Quelldatei verwenden kann, in der die Variable deklariert wurde.
Wenn Sie dies in einer mytest.cDatei deklarieren :
staticint my_variable;
Dann kann diese Variable nur aus dieser Datei gesehen werden. Die Variable kann nirgendwo anders exportiert werden.
Wenn Sie innerhalb einer Funktion deklarieren, behält der Wert der Variablen bei jedem Aufruf der Funktion seinen Wert.
Eine statische Funktion kann nicht von außerhalb der Datei exportiert werden. In einer *.cDatei verstecken Sie also die Funktionen und Variablen, wenn Sie sie als statisch deklarieren.
Statische Variablen in C haben die Lebensdauer des Programms.
Wenn sie in einer Funktion definiert sind, haben sie einen lokalen Bereich, dh sie können nur innerhalb dieser Funktionen aufgerufen werden. Der Wert statischer Variablen bleibt zwischen Funktionsaufrufen erhalten.
Im obigen Programm var wird im Datensegment gespeichert. Seine Lebensdauer ist das gesamte C-Programm.
Nach Funktionsaufruf 1 varwird 2. Nach Funktionsaufruf 2 varwird 3.
Der Wert von varwird zwischen Funktionsaufrufen nicht zerstört.
Wenn varzwischen nicht statischer und lokaler Variable, würde es im Stapelsegment im C-Programm gespeichert. Da der Stapelrahmen der Funktion nach der Rückkehr der Funktion zerstört wird, wird auch der Wert von varzerstört.
Initialisierte statische Variablen werden im Datensegment des C-Programms gespeichert, während nicht initialisierte im BSS-Segment gespeichert werden.
Weitere Informationen zu static: Wenn eine Variable global und statisch ist, hat sie die Lebensdauer des C-Programms, jedoch den Dateibereich. Es ist nur in dieser Datei sichtbar.
Um dies zu versuchen:
file1.c
staticint x;int main(){
printf("Accessing in same file%d", x):}
file2.c
externint x;
func(){
printf("accessing in different file %d",x);// Not allowed, x has the file scope of file1.c}
run gcc -c file1.c
gcc -c file2.c
Versuchen Sie nun, sie zu verknüpfen mit:
gcc -o output file1.o file2.o
Es würde einen Linkerfehler geben, da x den Dateibereich von file1.c hat und der Linker den in file2.c verwendeten Verweis auf die Variable x nicht auflösen kann.
Ich verstehe, dass die Daten persistent sind, was bedeutet, dass sie nicht nach jedem Funktionsaufruf verloren gehen, aber warum wird static int var = 1;der Wert nicht jedes Mal wieder auf eins geändert
Eames
3
Eine statische Variable ist eine spezielle Variable, die Sie in einer Funktion verwenden können. Sie speichert die Daten zwischen Aufrufen und löscht sie nicht zwischen Aufrufen. Zum Beispiel:
void func(){staticint count;// If you don't declare its value, the value automatically initializes to zero
printf("%d, ", count);++count;}void main(){while(true){
func();}}
Sie können durch printf("%d, ", count); count++;`printf ("% d, ", count ++) ersetzen (nicht, dass es darauf ankommt: P).
RastaJedi
2
Ein statischer Variablenwert bleibt zwischen verschiedenen Funktionsaufrufen bestehen und sein Gültigkeitsbereich ist auf den lokalen Block beschränkt, den eine statische Variable immer mit dem Wert 0 initialisiert
(1) Deklarierte lokale Variablen static: Wird im Datensegment anstelle des Stapels zugeordnet. Sein Wert bleibt erhalten, wenn Sie die Funktion erneut aufrufen.
(2) Deklarierte globale Variablen oder Funktionen static: Unsichtbar außerhalb der Kompilierungseinheit (dh lokale Symbole in der Symboltabelle während der Verknüpfung).
Statische Variablen haben die Eigenschaft , ihren Wert auch dann beizubehalten, wenn sie außerhalb ihres Gültigkeitsbereichs liegen. Daher behalten statische Variablen ihren vorherigen Wert in ihrem vorherigen Gültigkeitsbereich bei und werden im neuen Gültigkeitsbereich nicht erneut initialisiert.
Schauen Sie sich das zum Beispiel an - Eine statische int-Variable bleibt im Speicher, während das Programm ausgeführt wird. Eine normale oder automatische Variable wird zerstört, wenn ein Funktionsaufruf, bei dem die Variable deklariert wurde, beendet ist.
Da bleibt 1 im Speicher, da es als statisch deklariert wurde
Statische Variablen (wie globale Variablen) werden als 0 initialisiert, wenn sie nicht explizit initialisiert werden. Zum Beispiel wird im folgenden Programm der Wert von x als 0 gedruckt, während der Wert von y etwas Müll ist. Weitere Informationen finden Sie hier.
In der C-Programmierung staticist dies ein reserviertes Schlüsselwort, das sowohl die Lebensdauer als auch die Sichtbarkeit steuert. Wenn wir eine Variable innerhalb einer Funktion als statisch deklarieren, ist sie nur in dieser Funktion sichtbar. Bei dieser Verwendung beginnt die Lebensdauer dieser statischen Variablen bei einem Funktionsaufruf und wird nach Ausführung dieser Funktion zerstört. Sie können das folgende Beispiel sehen:
Denn sobald wir die Funktion aufrufen, wird die initialisiert count = 0. Und während wir das ausführen counterFunction, wird die Zählvariable zerstört.
> Das obige Programm gibt uns diesen Ausgang: Erster Zählerausgang = 1 Zweiter Zählerausgang = 1 <Nicht wahr. Statische Variablen werden nur einmal initialisiert. Die Ausgabe ist also 1, dann 2 und so weiter.
Antworten:
(1) ist das fremdere Thema, wenn Sie ein Neuling sind. Hier ist ein Beispiel:
Dies druckt:
Dies ist nützlich in Fällen, in denen eine Funktion einen bestimmten Status zwischen Aufrufen beibehalten muss und Sie keine globalen Variablen verwenden möchten. Beachten Sie jedoch, dass diese Funktion sehr sparsam verwendet werden sollte. Dadurch ist Ihr Code nicht threadsicher und schwerer zu verstehen.
(2) Wird häufig als "Zugangskontroll" -Funktion verwendet. Wenn Sie eine .c-Datei haben, die einige Funktionen implementiert, werden Benutzern normalerweise nur einige "öffentliche" Funktionen zur Verfügung gestellt. Der Rest seiner Funktionen sollte so ausgeführt werden
static
, dass der Benutzer nicht darauf zugreifen kann. Dies ist eine Kapselung, eine gute Praxis.Wikipedia zitieren :
Und um Ihre zweite Frage zu beantworten, ist es nicht wie in C #.
In C ++ wird es jedoch
static
auch verwendet, um Klassenattribute (die von allen Objekten derselben Klasse gemeinsam genutzt werden) und Methoden zu definieren. In C gibt es keine Klassen, daher ist diese Funktion irrelevant.quelle
.c
oder mehrere Header-Dateien sein, aber der Teufel befindet sich immer in dem, was nicht typisch ist.Es gibt eine weitere Verwendung, die hier nicht behandelt wird, und zwar als Teil einer Array-Typdeklaration als Argument für eine Funktion:
In diesem Zusammenhang gibt dies an, dass an diese Funktion übergebene Argumente ein Array vom Typ
char
mit mindestens 10 Elementen sein müssen. Für weitere Informationen siehe meine Frage hier .quelle
arg[0]
durcharg[9]
Werte zu haben (was bedeutet auch , dass die Funktion nicht einen Null - Zeiger nicht akzeptiert). Compiler könnten diese Informationen irgendwie zur Optimierung verwenden, und statische Analysatoren können diese Informationen verwenden, um sicherzustellen, dass der Funktion niemals ein Nullzeiger zugewiesen wird (oder, falls dies erkennbar ist, ein Array mit weniger Elementen als angegeben).static
in C99 angegeben wurde. Es ist mehr als anderthalb Jahrzehnte alt, aber nicht alle Compiler-Autoren haben alle C99-Funktionen übernommen - daher ist C99 insgesamt weitgehend unbekannt.int arr[n];
, dann ist das ein VLA (Array variabler Länge) , das in C99 hinzugefügt wurde. Ist es das, was du meintest?Kurze Antwort ... es kommt darauf an.
Statisch definierte lokale Variablen verlieren zwischen Funktionsaufrufen nicht ihren Wert. Mit anderen Worten, es handelt sich um globale Variablen, die sich jedoch auf die lokale Funktion beschränken, in der sie definiert sind.
Statische globale Variablen sind außerhalb der C-Datei, in der sie definiert sind, nicht sichtbar.
Statische Funktionen sind außerhalb der C-Datei, in der sie definiert sind, nicht sichtbar.
quelle
private
in C kein gibt, ist Ihre Analogie gut: statisch macht die Dinge für eine bestimmte Datei "privat". Und Dateien in C werden häufig Klassen in C ++ zugeordnet.Beispiel für einen Variablenbereich mit mehreren Dateien
Hier zeige ich, wie sich statisch auf den Umfang der Funktionsdefinitionen in mehreren Dateien auswirkt.
ac
Haupt c
GitHub stromaufwärts .
Kompilieren und ausführen:
Ausgabe:
Deutung
si
, eine für jede Dateii
Wie üblich, je kleiner der Bereich, desto besser. Deklarieren Sie daher immer Variablen
static
wenn Sie können.In der C-Programmierung werden Dateien häufig zur Darstellung von "Klassen" verwendet, und
static
Variablen repräsentieren private statische Mitglieder der Klasse.Was Standards dazu sagen
C99 N1256 Entwurf 6.7.1 "Speicherklassenspezifizierer" besagt dies
static
ein "Speicherklassenspezifizierer" ist.6.2.2 / 3 "Verknüpfungen von Kennungen"
static
impliziertinternal linkage
:und 6.2.2 / 2 sagt, dass
internal linkage
sich das wie in unserem Beispiel verhält:Dabei ist "Übersetzungseinheit eine Quelldatei nach der Vorverarbeitung.
Wie implementiert GCC es für ELF (Linux)?
Mit der
STB_LOCAL
Bindung.Wenn wir kompilieren:
und zerlegen Sie die Symboltabelle mit:
Die Ausgabe enthält:
Die Bindung ist also der einzige signifikante Unterschied zwischen ihnen.
Value
ist nur ihr Versatz in den.bss
Abschnitt, also erwarten wir, dass es anders ist.STB_LOCAL
ist in der ELF-Spezifikation unter http://www.sco.com/developers/gabi/2003-12-17/ch4.symtab.html dokumentiert :Das macht es zu einer perfekten Wahl für die Darstellung
static
.Variablen ohne statische Aufladung sind
STB_GLOBAL
und die Spezifikation sagt:Dies stimmt mit den Verknüpfungsfehlern bei mehreren nicht statischen Definitionen überein.
Wenn wir die Optimierung mit ankurbeln
-O3
, wird dassi
Symbol vollständig aus der Symboltabelle entfernt: Es kann sowieso nicht von außen verwendet werden. TODO warum statische Variablen überhaupt in der Symboltabelle belassen, wenn keine Optimierung erfolgt? Können sie für irgendetwas verwendet werden? Vielleicht zum Debuggen.Siehe auch
static
Funktionen: https://stackoverflow.com/a/30319812/895245static
mitextern
, was "das Gegenteil" bedeutet: Wie verwende ich extern, um Variablen zwischen Quelldateien zu teilen?Anonyme C ++ - Namespaces
In C ++ möchten Sie möglicherweise anonyme Namespaces anstelle von statischen verwenden, wodurch ein ähnlicher Effekt erzielt wird. Die Typdefinitionen werden jedoch weiter ausgeblendet: Unbenannte / anonyme Namespaces im Vergleich zu statischen Funktionen
quelle
Es hängt davon ab, ob:
Die Funktion würde 1, 2, 3 usw. zurückgeben. --- Die Variable befindet sich nicht auf dem Stapel.
ac:
Dies bedeutet, dass diese Funktion nur in dieser Datei Gültigkeitsbereich hat. AC und bc können also unterschiedliche
foo()
s haben, und foo ist keinen gemeinsam genutzten Objekten ausgesetzt. Wenn Sie also foo in ac definiert haben, können Sie nicht vonb.c
oder von anderen Orten darauf zugreifen .In den meisten C-Bibliotheken sind alle "privaten" Funktionen statisch und die meisten "öffentlichen" nicht.
quelle
Die Leute sagen immer wieder, dass 'statisch' in C zwei Bedeutungen hat. Ich biete eine alternative Sichtweise an, die ihm eine einzige Bedeutung gibt:
Der Grund, warum es zwei Bedeutungen zu haben scheint, ist, dass in C jedes Element, auf das 'statisch' angewendet werden kann, bereits eine dieser beiden Eigenschaften hat , so dass es den Anschein hat, als ob diese bestimmte Verwendung nur die andere betrifft.
Betrachten Sie beispielsweise Variablen. Variablen, die außerhalb von Funktionen deklariert wurden, haben bereits eine Persistenz (im Datensegment). Wenn Sie also 'static' anwenden, können sie nur außerhalb des aktuellen Bereichs (Kompilierungseinheit) nicht sichtbar gemacht werden. Im Gegensatz dazu sind Variablen, die innerhalb von Funktionen deklariert wurden, bereits außerhalb des aktuellen Bereichs (Funktion) nicht sichtbar, sodass die Anwendung von 'statisch' sie nur dauerhaft machen kann.
Das Anwenden von 'statisch' auf Funktionen ist wie das Anwenden auf globale Variablen - Code ist notwendigerweise persistent (zumindest innerhalb der Sprache), sodass nur die Sichtbarkeit geändert werden kann.
HINWEIS: Diese Kommentare gelten nur für C. In C ++ gibt das Anwenden von 'static' auf Klassenmethoden dem Schlüsselwort eine andere Bedeutung. Ähnliches gilt für die C99-Array-Argument-Erweiterung.
quelle
static
gibt eine interne Verknüpfung zu einem Bezeichner.Aus Wikipedia:
quelle
static
bedeutet verschiedene Dinge in verschiedenen Kontexten.Sie können eine statische Variable in einer C-Funktion deklarieren. Diese Variable ist nur in der Funktion sichtbar, verhält sich jedoch insofern wie eine globale, als sie nur einmal initialisiert wird und ihren Wert beibehält. In diesem Beispiel wird bei jedem Anruf
foo()
eine zunehmende Zahl gedruckt. Die statische Variable wird nur einmal initialisiert.Eine andere Verwendung von statisch ist, wenn Sie eine Funktion oder eine globale Variable in einer .c-Datei implementieren, deren Symbol jedoch nicht außerhalb der
.obj
von der Datei generierten sichtbar sein soll . z.Bquelle
Wenn Sie eine Variable in einer statischen Funktion deklarieren, wird ihr Wert nicht im Funktionsaufrufstapel gespeichert und ist weiterhin verfügbar, wenn Sie die Funktion erneut aufrufen.
Wenn Sie eine globale Variable als statisch deklarieren, wird ihr Gültigkeitsbereich auf die Datei beschränkt, in der Sie sie deklariert haben. Dies ist etwas sicherer als ein reguläres globales Programm, das im gesamten Programm gelesen und geändert werden kann.
quelle
Ich hasse es, eine alte Frage zu beantworten, aber ich glaube, niemand hat erwähnt, wie K & R sie in Abschnitt A4.1 von "The C Programming Language" erklärt.
Kurz gesagt, das Wort statisch wird mit zwei Bedeutungen verwendet:
static
Schlüsselwort (wobei der Schwerpunkt darauf liegt, dass es im Code als Schlüsselwort verwendet wird) mit einer Deklaration verwendet wird, wird das Objekt intern verknüpft, sodass es nur innerhalb dieser Übersetzungseinheit verwendet werden kann. Wenn das Schlüsselwort jedoch in einer Funktion verwendet wird, ändert es die Speicherklasse des Objekts (das Objekt wäre ohnehin nur in dieser Funktion sichtbar). Das Gegenteil von statisch ist dasextern
Schlüsselwort, das eine externe Verknüpfung eines Objekts ergibt.Peter Van Der Linden gibt diese beiden Bedeutungen in "Expert C Programming" an:
quelle
register
einen Speicherklassenspezifizierer darstellt (C99 6.7.1 Speicherklassenspezifizierer). Und es ist mehr als nur ein Hinweis: Sie können beispielsweise den Adressoperator nicht&
auf ein Objekt mit Speicherklasse anwenden,register
unabhängig davon, ob der Compiler ein Register zuweist oder nicht.In C hat statisch je nach Anwendungsbereich zwei Bedeutungen. Wenn im globalen Bereich ein Objekt auf Dateiebene deklariert wird, bedeutet dies, dass dieses Objekt nur in dieser Datei sichtbar ist.
In jedem anderen Bereich wird ein Objekt deklariert, das seinen Wert zwischen den verschiedenen Zeitpunkten beibehält, zu denen der bestimmte Bereich eingegeben wird. Wenn beispielsweise ein int innerhalb einer Prozedur gelöscht wird:
Der Wert von 'i' wird beim ersten Aufruf der Prozedur auf Null initialisiert, und der Wert bleibt bei jedem weiteren Aufruf der Prozedur erhalten. Wenn 'i' gedruckt würde, würde eine Folge von 0, 1, 2, 3, ... ausgegeben.
quelle
Es ist wichtig zu beachten, dass statische Variablen in Funktionen beim ersten Eintrag in diese Funktion initialisiert werden und auch nach Beendigung ihres Aufrufs bestehen bleiben. Bei rekursiven Funktionen wird die statische Variable nur einmal initialisiert und bleibt auch bei allen rekursiven Aufrufen und auch nach Beendigung des Funktionsaufrufs bestehen.
Wenn die Variable außerhalb einer Funktion erstellt wurde, bedeutet dies, dass der Programmierer die Variable nur in der Quelldatei verwenden kann, in der die Variable deklariert wurde.
quelle
Wenn Sie dies in einer
mytest.c
Datei deklarieren :Dann kann diese Variable nur aus dieser Datei gesehen werden. Die Variable kann nirgendwo anders exportiert werden.
Wenn Sie innerhalb einer Funktion deklarieren, behält der Wert der Variablen bei jedem Aufruf der Funktion seinen Wert.
Eine statische Funktion kann nicht von außerhalb der Datei exportiert werden. In einer
*.c
Datei verstecken Sie also die Funktionen und Variablen, wenn Sie sie als statisch deklarieren.quelle
Statische Variablen in C haben die Lebensdauer des Programms.
Wenn sie in einer Funktion definiert sind, haben sie einen lokalen Bereich, dh sie können nur innerhalb dieser Funktionen aufgerufen werden. Der Wert statischer Variablen bleibt zwischen Funktionsaufrufen erhalten.
Zum Beispiel:
Im obigen Programm
var
wird im Datensegment gespeichert. Seine Lebensdauer ist das gesamte C-Programm.Nach Funktionsaufruf 1
var
wird 2. Nach Funktionsaufruf 2var
wird 3.Der Wert von
var
wird zwischen Funktionsaufrufen nicht zerstört.Wenn
var
zwischen nicht statischer und lokaler Variable, würde es im Stapelsegment im C-Programm gespeichert. Da der Stapelrahmen der Funktion nach der Rückkehr der Funktion zerstört wird, wird auch der Wert vonvar
zerstört.Initialisierte statische Variablen werden im Datensegment des C-Programms gespeichert, während nicht initialisierte im BSS-Segment gespeichert werden.
Weitere Informationen zu static: Wenn eine Variable global und statisch ist, hat sie die Lebensdauer des C-Programms, jedoch den Dateibereich. Es ist nur in dieser Datei sichtbar.
Um dies zu versuchen:
file1.c
file2.c
Versuchen Sie nun, sie zu verknüpfen mit:
Es würde einen Linkerfehler geben, da x den Dateibereich von file1.c hat und der Linker den in file2.c verwendeten Verweis auf die Variable x nicht auflösen kann.
Verweise:
quelle
static int var = 1;
der Wert nicht jedes Mal wieder auf eins geändertEine statische Variable ist eine spezielle Variable, die Sie in einer Funktion verwenden können. Sie speichert die Daten zwischen Aufrufen und löscht sie nicht zwischen Aufrufen. Zum Beispiel:
Die Ausgabe:
quelle
printf("%d, ", count); count++;
`printf ("% d, ", count ++) ersetzen (nicht, dass es darauf ankommt: P).Ein statischer Variablenwert bleibt zwischen verschiedenen Funktionsaufrufen bestehen und sein Gültigkeitsbereich ist auf den lokalen Block beschränkt, den eine statische Variable immer mit dem Wert 0 initialisiert
quelle
Es gibt 2 Fälle:
(1) Deklarierte lokale Variablen
static
: Wird im Datensegment anstelle des Stapels zugeordnet. Sein Wert bleibt erhalten, wenn Sie die Funktion erneut aufrufen.(2) Deklarierte globale Variablen oder Funktionen
static
: Unsichtbar außerhalb der Kompilierungseinheit (dh lokale Symbole in der Symboltabelle während der Verknüpfung).quelle
Statische Variablen haben die Eigenschaft , ihren Wert auch dann beizubehalten, wenn sie außerhalb ihres Gültigkeitsbereichs liegen. Daher behalten statische Variablen ihren vorherigen Wert in ihrem vorherigen Gültigkeitsbereich bei und werden im neuen Gültigkeitsbereich nicht erneut initialisiert.
Schauen Sie sich das zum Beispiel an - Eine statische int-Variable bleibt im Speicher, während das Programm ausgeführt wird. Eine normale oder automatische Variable wird zerstört, wenn ein Funktionsaufruf, bei dem die Variable deklariert wurde, beendet ist.
Dies gibt Folgendes aus: 1 2
Da bleibt 1 im Speicher, da es als statisch deklariert wurde
Statische Variablen (wie globale Variablen) werden als 0 initialisiert, wenn sie nicht explizit initialisiert werden. Zum Beispiel wird im folgenden Programm der Wert von x als 0 gedruckt, während der Wert von y etwas Müll ist. Weitere Informationen finden Sie hier.
Dies gibt Folgendes aus: 0 [some_garbage_value]
Dies sind die wichtigsten, die ich gefunden habe und die oben für einen Neuling nicht erklärt wurden!
quelle
In der C-Programmierung
static
ist dies ein reserviertes Schlüsselwort, das sowohl die Lebensdauer als auch die Sichtbarkeit steuert. Wenn wir eine Variable innerhalb einer Funktion als statisch deklarieren, ist sie nur in dieser Funktion sichtbar. Bei dieser Verwendung beginnt die Lebensdauer dieser statischen Variablen bei einem Funktionsaufruf und wird nach Ausführung dieser Funktion zerstört. Sie können das folgende Beispiel sehen:Das obige Programm gibt uns diese Ausgabe:
Denn sobald wir die Funktion aufrufen, wird die initialisiert
count = 0
. Und während wir das ausführencounterFunction
, wird die Zählvariable zerstört.quelle