Was bedeutet "statisch" in C?

1136

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)?

jww
quelle
6
Siehe auch: Statisch (Stichwort) @ Wikipedia
Palec
15
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/…
Ciro Santilli 法轮功 病毒 审查 六四 事件 法轮功

Antworten:

1519
  1. Eine statische Variable innerhalb einer Funktion behält ihren Wert zwischen Aufrufen bei.
  2. 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;
    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 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.

Eli Bendersky
quelle
179
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[static 10])
{
    ...
}

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 .

Dreamlax
quelle
3
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.

  1. 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.

  2. Statische globale Variablen sind außerhalb der C-Datei, in der sie definiert sind, nicht sichtbar.

  3. Statische Funktionen sind außerhalb der C-Datei, in der sie definiert sind, nicht sichtbar.

cmcginty
quelle
8
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. */
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;
}

GitHub stromaufwärts .

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

  • 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;
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. Valueist nur ihr Versatz in den .bssAbschnitt, also erwarten wir, dass es anders ist.

STB_LOCAList 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_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.

Siehe auch

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

Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功
quelle
39

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.

ac:

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.coder von anderen Orten darauf zugreifen .

In den meisten C-Bibliotheken sind alle "privaten" Funktionen statisch und die meisten "öffentlichen" nicht.

Artyom
quelle
18
+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.

PMar
quelle
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.

OscarRyz
quelle
16

static bedeutet verschiedene Dinge in verschiedenen Kontexten.

  1. 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++
    }
  2. 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

    static void foo() { ... }
mis
quelle
8

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.

Jonathan Adelson
quelle
8

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:

  1. 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.
  2. Wenn das 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 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.
  • Auf Funktionsebene nur in dieser Datei sichtbar.
Jigglypuff
quelle
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)
{
   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.

schot
quelle
5

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.

Starhowl
quelle
5

Wenn Sie dies in einer mytest.cDatei 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 *.cDatei verstecken Sie also die Funktionen und Variablen, wenn Sie sie als statisch deklarieren.

ant2009
quelle
4

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 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

static int x;

int main()
{
    printf("Accessing in same file%d", x):
}

file2.c

    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:

  1. http://en.wikipedia.org/wiki/Translation_unit_(programming)
  2. http://en.wikipedia.org/wiki/Call_stack
Sahil Manchanda
quelle
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(){
    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, ...

Yagel
quelle
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

Jonathon
quelle
2

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).

Jonny Kong
quelle
1

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!

Erastone
quelle
-1

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:

#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.

Makdia Hussain
quelle
2
> 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.
GermanNerd