Ich habe das Wort static
an verschiedenen Stellen im C-Code gesehen. Ist dies wie eine statische Funktion / Klasse in C # (wo die Implementierung von mehreren Objekten gemeinsam genutzt wird)?
Ich habe das Wort static
an verschiedenen Stellen im C-Code gesehen. Ist dies wie eine statische Funktion / Klasse in C # (wo die Implementierung von mehreren Objekten gemeinsam genutzt wird)?
Antworten:
(1) ist das fremdere Thema, wenn Sie ein Neuling sind. Hier ist ein Beispiel:
#include <stdio.h>
void foo()
{
int a = 10;
static int 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.
Wikipedia zitieren :
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 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.
.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:
int someFunction(char arg[static 10])
{
...
}
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 .
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).
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.
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
#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. */
extern int i;
/* OK: only visible to this file. */
static int si = 0;
void a() {
i++;
si++;
puts("a()");
printf("i = %d\n", i);
printf("si = %d\n", si);
puts("");
}
Haupt c
#include <stdio.h>
int i = 0;
static int si = 0;
void a();
void m() {
i++;
si++;
puts("m()");
printf("i = %d\n", i);
printf("si = %d\n", si);
puts("");
}
int main() {
m();
m();
a();
a();
return 0;
}
Kompilieren und ausführen:
gcc -c a.c -o a.o
gcc -c main.c -o main.o
gcc -o main main.o a.o
Ausgabe:
m()
i = 1
si = 1
m()
i = 2
si = 2
a()
i = 3
si = 1
a()
i = 4
si = 2
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 diesstatic
ein "Speicherklassenspezifizierer" ist.
6.2.2 / 3 "Verknüpfungen von Kennungen" static
impliziert 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 linkage
sich 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_LOCAL
Bindung.
Wenn wir kompilieren:
int i = 0;
static int si = 0;
und zerlegen Sie die Symboltabelle mit:
readelf -s main.o
Die Ausgabe enthält:
Num: Value Size Type Bind Vis Ndx Name
5: 0000000000000004 4 OBJECT LOCAL DEFAULT 4 si
10: 0000000000000000 4 OBJECT GLOBAL DEFAULT 4 i
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 :
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_GLOBAL
und 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 si
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
mit extern
, 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
Es hängt davon ab, ob:
int foo()
{
static int x;
return ++x;
}
Die Funktion würde 1, 2, 3 usw. zurückgeben. --- Die Variable befindet sich nicht auf dem Stapel.
static int 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.c
oder von anderen Orten darauf zugreifen .
In den meisten C-Bibliotheken sind alle "privaten" Funktionen statisch und die meisten "öffentlichen" nicht.
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.
static
gibt eine interne Verknüpfung zu einem Bezeichner.
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 ()
{
static int 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 .obj
von der Datei generierten sichtbar sein soll . z.B
static void foo() { ... }
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:
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 das extern
Schlüsselwort, das eine externe Verknüpfung eines Objekts ergibt.Peter Van Der Linden gibt diese beiden Bedeutungen in "Expert C Programming" an:
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:
void procedure(void)
{
static int 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.c
Datei deklarieren :
static int 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 *.c
Datei 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.
Zum Beispiel:
void function()
{
static int var = 1;
var++;
printf("%d", var);
}
int main()
{
function(); // Call 1
function(); // Call 2
}
Im obigen Programm var
wird im Datensegment gespeichert. Seine Lebensdauer ist das gesamte C-Programm.
Nach Funktionsaufruf 1 var
wird 2. Nach Funktionsaufruf 2 var
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 von var
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:
static int x;
int main()
{
printf("Accessing in same file%d", x):
}
extern int 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.
Verweise:
static int var = 1;
der Wert nicht jedes Mal wieder auf eins geändert
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(){
static int count; // If you don't declare its value, the value automatically initializes to zero
printf("%d, ", count);
++count;
}
void main(){
while(true){
func();
}
}
Die Ausgabe:
0, 1, 2, 3, 4, 5, ...
printf("%d, ", count); count++;
`printf ("% d, ", count ++) ersetzen (nicht, dass es darauf ankommt: P).
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).
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.
#include<stdio.h>
int fun()
{
static int count = 0;
count++;
return count;
}
int main()
{
printf("%d ", fun());
printf("%d ", fun());
return 0;
}
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.
#include <stdio.h>
int main()
{
static int x;
int y;
printf("%d \n %d", x, y);
}
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!
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:
#include<stdio.h>
int counterFunction()
{
static int count = 0;
count++;
return count;
}
int main()
{
printf("First Counter Output = %d\n", counterFunction());
printf("Second Counter Output = %d ", counterFunction());
return 0;
}
Das obige Programm gibt uns diese Ausgabe:
First Counter Output = 1
Second Counter Output = 1
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.