Co oznacza „statyczny” w C?


1135

Widziałem słowo staticużywane w różnych miejscach w kodzie C; czy to jest jak statyczna funkcja / klasa w C # (gdzie implementacja jest współdzielona między obiektami)?



15
Jaki jest powód do usunięcia „w programie C” na końcu tytułu @Lundin? Jest nieco redundantny w obecności tagu c , ale pozwala mi szybciej zobaczyć kategoryzację, bez sprawdzania tagów. Ta nadmiarowość jest bardzo wygodna, gdy docieram do pytania z kierunku, który może zawierać również pytania dotyczące innych języków, np. Statycznych lub wyszukiwarki Google.
Palec

5
@Palec Istnieje zasada SO, zgodnie z którą elementy znajdujące się na liście tagów są zbędne w tytule. Witryna automatycznie doda C do rzeczywistej strony internetowej. Google dla „C static” daje tę odpowiedź jako najlepszy hit. Powodem, dla którego to zmieniono, jest to, że pytanie to jest teraz częścią FAQ języka SO C, a wszystkie dodane posty są nieco dopracowane.
Lundin

1
@Lundin Wolę zachować „C” w tytule, ponieważ SO dołącza tylko jeden tag do tytułu (najczęściej?). Co się stanie, jeśli pewnego dnia „składnia” osiągnie więcej pytań niż C (ponieważ jest to sprawa międzyjęzykowa)? Wolę użyć jawnego zachowania :-) Edytuj: ah, ale istnieje meta pytanie, które mówi inaczej: meta.stackexchange.com/questions/19190/...
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功

1
To wyjaśnienie znalazłem na Quora. Zdecydowanie warto przeczytać!
nalzok

Odpowiedzi:


1519
  1. Zmienna statyczna wewnątrz funkcji zachowuje swoją wartość między wywołaniami.
  2. Statyczna zmienna globalna lub funkcja jest „widoczna” tylko w pliku, w którym została zadeklarowana

(1) jest bardziej zagranicznym tematem, jeśli jesteś nowicjuszem, więc oto przykład:

#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();
}

To drukuje:

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

Jest to przydatne w przypadkach, gdy funkcja musi zachować pewien stan między wywołaniami, a nie chcesz używać zmiennych globalnych. Uważaj jednak, ta funkcja powinna być używana bardzo oszczędnie - sprawia, że ​​twój kod nie jest bezpieczny dla wątków i trudniejszy do zrozumienia.

(2) Jest szeroko stosowany jako funkcja „kontroli dostępu”. Jeśli masz plik .c implementujący pewne funkcje, zwykle udostępnia użytkownikom tylko kilka funkcji „publicznych”. Reszta funkcji powinna zostać wykonana static, aby użytkownik nie mógł uzyskać do nich dostępu. To jest kapsułkowanie, dobra praktyka.

Cytując Wikipedię :

W języku programowania C statyczny jest używany ze zmiennymi globalnymi i funkcjami w celu ustawienia ich zakresu na plik zawierający. W zmiennych lokalnych statyczny służy do przechowywania zmiennej w pamięci przydzielonej statycznie zamiast w pamięci przydzielanej automatycznie. Chociaż język nie dyktuje implementacji żadnego rodzaju pamięci, pamięć przydzielona statycznie jest zwykle zarezerwowana w segmencie danych programu w czasie kompilacji, podczas gdy pamięć przydzielana automatycznie jest zwykle implementowana jako stos wywołań przejściowych.

Aby odpowiedzieć na twoje drugie pytanie, to nie jest tak jak w C #.

Jednak w C ++ staticsłuży również do definiowania atrybutów klas (współdzielonych przez wszystkie obiekty tej samej klasy) i metod. W C nie ma klas, więc ta funkcja jest nieistotna.


179
Pax, OP nie wie o statyce, więc sugerujesz zanurzenie go w różnicy między jednostkami kompilacji a plikami? :-)
Eli Bendersky

138
Kompilator to pojedynczy plik, który kompilator widzi. Twój plik .c może zawierać inne pliki .c, ale po tym, jak preprocesor posortuje załączniki, kompilator ostatecznie zobaczy tylko jedną „jednostkę kompilacji”.
Eli Bendersky

81
@robUK: kompilator nawet nie wie o plikach .h - są one łączone w pliki .c w preprocesorze. Tak, można powiedzieć, że plik .c, ze wszystkimi zawartymi w nim nagłówkami, jest pojedynczą jednostką kompilacji.
Eli Bendersky

6
@TonyD może to mylące, ale tak działa kompilacja. Zwykle może to być jeden .ci kilka plików nagłówkowych, ale diabeł zawsze jest w tym, co nie jest typowe.
peterph

7
@TonyD Kompilator wykonuje kompilację. Preprocesor wykonuje przetwarzanie wstępne. Nazwanie zestawu narzędzi „kompilatorem” nie zmienia tego, czym jest ani co robi.
Miles Rout,

231

Jest jeszcze jedno zastosowanie, które nie zostało tutaj omówione, i które jest częścią deklaracji typu tablicy jako argumentu funkcji:

int someFunction(char arg[static 10])
{
    ...
}

W tym kontekście oznacza to, że argumenty przekazywane do tej funkcji muszą być tablicą typu charz co najmniej 10 elementami. Aby uzyskać więcej informacji, zobacz moje pytanie tutaj .


3
Nie sądziłem, że C ma argumenty tablicowe? Linus Torvalds wścieka się na ludzi, którzy to robią.
suprjami

13
@jamieb: C nie ma argumentów tablicy, ale to konkretne środki składniowe, że spodziewa funkcyjne arg[0]poprzez aby arg[9]mieć wartości (co oznacza również, że funkcja nie przyjmuje wskaźnik NULL). Kompilatory mogą w jakiś sposób wykorzystać te informacje do optymalizacji, a analizatory statyczne mogą wykorzystać te informacje, aby upewnić się, że funkcja nigdy nie otrzyma wskaźnika zerowego (lub jeśli może powiedzieć, tablicę z mniejszą liczbą elementów niż podano).
dreamlax

19
@Qix - To było nowe przeciążone znaczenie nadane staticw C99. Ma ponad półtorej dekady, ale nie wszyscy autorzy kompilatorów przyjęli wszystkie funkcje C99 - więc C99 jako całość pozostaje w dużej mierze nieznana.
Happy Green Kid Naps

@ suprjami Nie jestem w 100% pewien, co rozumiesz przez „argumenty tablicowe” , ale jeśli masz na myśli int arr[n];, to jest to VLA (tablica o zmiennej długości) , która została dodana w C99. Czy o to ci chodziło?
RastaJedi

170

Krótka odpowiedź ... to zależy.

  1. Zmienne lokalne zdefiniowane statycznie nie tracą swojej wartości między wywołaniami funkcji. Innymi słowy, są to zmienne globalne, ale mają zakres funkcji lokalnej, w której są zdefiniowane.

  2. Statyczne zmienne globalne nie są widoczne poza plikiem C, w którym są zdefiniowane.

  3. Funkcje statyczne nie są widoczne poza plikiem C, w którym są zdefiniowane.


8
Czy zatem „funkcja statyczna” i „funkcja prywatna” oznaczają to samo? Podobnie „statyczne zmienne globalne” i „prywatne zmienne globalne” to to samo?
user1599964,

40
Chodzi o C. Nie ma prywatnego / publicznego w C.
Chris

19
@ user1599964 chociaż nie ma privatew C, twoja analogia jest dobra: statyczna czyni rzeczy „prywatnymi” dla danego pliku. Pliki w C często odwzorowują klasy w C ++.
Ciro Santilli 23 病毒 审查 六四 事件 法轮功

66

Przykład wielu zakresów zmiennych

Tutaj ilustruję, jak statyczny wpływa na zakres definicji funkcji w wielu plikach.

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("");
}

main.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 w górę .

Skompiluj i uruchom:

gcc -c a.c -o a.o
gcc -c main.c -o main.o
gcc -o main main.o a.o

Wynik:

m()
i = 1
si = 1

m()
i = 2
si = 2

a()
i = 3
si = 1

a()
i = 4
si = 2

Interpretacja

  • istnieją dwie osobne zmienne si, po jednej dla każdego pliku
  • istnieje jedna wspólna zmienna dla i

Jak zwykle, im mniejszy zakres, tym lepiej, więc zawsze deklaruj zmienne, staticjeśli możesz.

W programowaniu C pliki są często używane do reprezentowania „klas”, a staticzmienne reprezentują prywatnych statycznych członków klasy.

Co mówią o tym standardy

C99 N1256 wersja robocza 6.7.1 „ Specyfikatory klasy pamięci” mówią, że staticjest to „specyfikator klasy pamięci”.

6.2.2 / 3 „Powiązania identyfikatorów” mówi staticzakłada internal linkage:

Jeśli deklaracja identyfikatora zakresu pliku dla obiektu lub funkcji zawiera statyczny specyfikator klasy pamięci, identyfikator ma wewnętrzne powiązanie.

a 6.2.2 / 2 mówi, że internal linkagezachowuje się jak w naszym przykładzie:

W zestawie jednostek tłumaczeniowych i bibliotek, które stanowią cały program, każda deklaracja określonego identyfikatora z zewnętrznym powiązaniem oznacza ten sam obiekt lub funkcję. W obrębie jednej jednostki tłumaczeniowej każda deklaracja identyfikatora z wewnętrznym powiązaniem oznacza ten sam obiekt lub funkcję.

gdzie „jednostka tłumacząca jest plikiem źródłowym po wstępnym przetwarzaniu.

Jak GCC implementuje to dla ELF (Linux)?

Z STB_LOCALwiązaniem.

Jeśli skompilujemy:

int i = 0;
static int si = 0;

i zdemontować tabelę symboli za pomocą:

readelf -s main.o

wyjście zawiera:

Num:    Value          Size Type    Bind   Vis      Ndx Name
  5: 0000000000000004     4 OBJECT  LOCAL  DEFAULT    4 si
 10: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    4 i

więc wiązanie jest jedyną znaczącą różnicą między nimi. Valuejest tylko ich przesunięciem do .bsssekcji, więc spodziewamy się, że będzie się różnić.

STB_LOCALjest udokumentowany w specyfikacji ELF pod adresem http://www.sco.com/developers/gabi/2003-12-17/ch4.symtab.html :

STB_LOCAL Symbole lokalne nie są widoczne poza plikiem obiektowym zawierającym ich definicję. Lokalne symbole o tej samej nazwie mogą istnieć w wielu plikach bez kolidowania ze sobą

co czyni go idealnym wyborem do reprezentowania static.

Zmienne bez wartości statycznych są STB_GLOBAL, a specyfikacja mówi:

Gdy edytor łączy łączy kilka plików obiektów relokowalnych, nie pozwala na wiele definicji symboli STB_GLOBAL o tej samej nazwie.

co jest spójne z błędami łącza w wielu definicjach niestatycznych.

Jeśli zwiększymy optymalizację za pomocą -O3, sisymbol zostanie całkowicie usunięty z tabeli symboli: i tak nie można go używać z zewnątrz. TODO, po co w ogóle przechowywać zmienne statyczne w tabeli symboli, gdy nie ma optymalizacji? Czy można ich używać do czegokolwiek? Może do debugowania.

Zobacz też

Anonimowe przestrzenie nazw C ++

W C ++ możesz użyć anonimowych przestrzeni nazw zamiast statycznych, co daje podobny efekt, ale dodatkowo ukrywa definicje typów: Bezimienne / anonimowe przestrzenie nazw vs. funkcje statyczne


39

To zależy:

int foo()
{
   static int x;
   return ++x;
}

Funkcja zwróci 1, 2, 3 itd. --- zmiennej nie ma na stosie.

ac:

static int foo()
{
}

Oznacza to, że ta funkcja ma zakres tylko w tym pliku. Zatem ac i bc mogą mieć różne foo()s, a foo nie jest narażone na współdzielone obiekty. Więc jeśli zdefiniowałeś foo in ac, nie możesz uzyskać do niego dostępu z b.club z innych miejsc.

W większości bibliotek C wszystkie „prywatne” funkcje są statyczne, a większość „publicznych” nie.


18
+1 za wzmiankę o x nie na stosie lub stosie. Jest w statycznej przestrzeni pamięci.
Gob00st

1
@ Gob00st statyczna przestrzeń pamięci? miałeś na myśli „Segment danych” ...?
Yousha Aleayoub,

24

Ludzie ciągle mówią, że „statyczny” w C ma dwa znaczenia. Oferuję alternatywny sposób oglądania, który nadaje mu jedno znaczenie:

  • Zastosowanie elementu „statycznego” do elementu zmusza go do posiadania dwóch właściwości: (a) Nie jest widoczny poza bieżącym zakresem; (b) Jest trwały.

Wydaje się, że ma to dwa znaczenia, ponieważ w C każdy element, do którego można zastosować „statyczny”, ma już jedną z tych dwóch właściwości , więc wydaje się , że to konkretne użycie dotyczy tylko drugiej.

Rozważmy na przykład zmienne. Zmienne zadeklarowane poza funkcjami mają już trwałość (w segmencie danych), więc zastosowanie parametru „static” może sprawić, że nie będą widoczne poza bieżącym zakresem (jednostka kompilacji). Przeciwnie, zmienne zadeklarowane wewnątrz funkcji już nie są widoczne poza bieżącym zakresem (funkcją), więc zastosowanie „statycznego” może tylko je utrwalić.

Zastosowanie „statycznego” do funkcji jest tak samo jak zastosowanie go do zmiennych globalnych - kod jest koniecznie trwały (przynajmniej w języku), więc można zmienić tylko widoczność.

UWAGA: Te komentarze dotyczą tylko C. W C ++ zastosowanie „statycznego” do metod klasowych naprawdę nadaje słowu kluczowemu inne znaczenie. Podobnie w przypadku rozszerzenia argument-tablica C99.


Twoje (a) jest co najwyżej zbędne. Żadna zmienna nie jest widoczna poza jej zakresem. To po prostu definicja zakresu. To, co masz na myśli, nazywa się linkage w standardzie C. staticdaje wewnętrzne powiązanie z identyfikatorem.
Jens

16

Z Wikipedii:

W języku programowania C statyczny jest używany ze zmiennymi globalnymi i funkcjami w celu ustawienia ich zakresu na plik zawierający. W zmiennych lokalnych statyczny służy do przechowywania zmiennej w pamięci przydzielonej statycznie zamiast w pamięci przydzielanej automatycznie. Chociaż język nie dyktuje implementacji żadnego rodzaju pamięci, pamięć przydzielona statycznie jest zwykle zarezerwowana w segmencie danych programu w czasie kompilacji, podczas gdy pamięć przydzielana automatycznie jest zwykle implementowana jako stos wywołań przejściowych.


16

static oznacza różne rzeczy w różnych kontekstach.

  1. Możesz zadeklarować zmienną statyczną w funkcji C. Ta zmienna jest widoczna tylko w funkcji, jednak zachowuje się jak globalna, ponieważ jest inicjowana tylko raz i zachowuje swoją wartość. W tym przykładzie za każdym razem, foo()gdy zadzwonisz , wydrukuje rosnący numer. Zmienna statyczna jest inicjowana tylko raz.

    void foo ()
    {
    static int i = 0;
    printf("%d", i); i++
    }
  2. Innym zastosowaniem statycznego jest zaimplementowanie funkcji lub zmiennej globalnej w pliku .c, ale nie chcesz, aby jej symbol był widoczny poza .objgenerowanym przez plik. na przykład

    static void foo() { ... }

8

Jeśli zadeklarujesz zmienną w funkcji statycznej, jej wartość nie zostanie zapisana na stosie wywołań funkcji i będzie nadal dostępna po ponownym wywołaniu funkcji.

Jeśli zadeklarujesz zmienną globalną statyczną, jej zakres będzie ograniczony do pliku, w którym ją zadeklarowałeś. Jest to nieco bezpieczniejsze niż zwykłe globalne, które można czytać i modyfikować w całym programie.


8

Nienawidzę odpowiadać na stare pytanie, ale nie sądzę, żeby ktokolwiek wspomniał, jak K&R wyjaśnia to w sekcji A4.1 „The C Programming Language”.

Krótko mówiąc, słowo statyczne ma dwa znaczenia:

  1. Statyczna jest jedną z dwóch klas pamięci (druga jest automatyczna). Obiekt statyczny zachowuje swoją wartość między wywołaniami. Obiekty zadeklarowane poza wszystkimi blokami są zawsze statyczne i nie mogą być automatyczne.
  2. Ale gdy static słowo kluczowe (duży nacisk na użycie go w kodzie jako słowo kluczowe) jest używane z deklaracją, daje to wewnętrznemu powiązaniu obiektu, więc można go używać tylko w obrębie tej jednostki tłumaczeniowej. Ale jeśli słowo kluczowe jest używane w funkcji, zmienia klasę pamięci obiektu (obiekt i tak byłby widoczny tylko w tej funkcji). Przeciwieństwem statycznego jest externsłowo kluczowe, które daje obiektowi zewnętrzne powiązanie.

Peter Van Der Linden nadaje te dwa znaczenia w „Expert C Programming”:

  • Wewnątrz funkcji zachowuje swoją wartość między wywołaniami.
  • Na poziomie funkcji, widoczne tylko w tym pliku.

Jest trzecia klasa pamięci, zarejestruj się . Niektóre osoby opowiadają się również za czwartą klasą przechowywania przydzieloną dla magazynu zwróconego przez malloc i przyjaciół.
Jens

@Jens „register” jest jedynie wskazówką dla kompilatora; pamięci rejestru nie można wymuszać ze źródła C. Więc nie uważałbym tego za klasę pamięci.
GermanNerd

1
@GermanNerd Obawiam się, że nie zgadza ISO C Standard z widoku, jak to wyraźnie czyni registersię specyfikator przechowywania klasy (C99 6.7.1 Przechowywanie klasy SPECYFIKATORY). Jest to coś więcej niż tylko wskazówka, na przykład nie można zastosować operatora adresu &do obiektu z klasą pamięci, registerniezależnie od tego, czy kompilator przydzieli rejestr, czy nie.
Jens

@Jens Dzięki za przypomnienie mi o &. Mogłem zrobić za dużo C ++ ... W każdym razie, chociaż „register” jest specyfikatorem klasy pamięci, w rzeczywistości kompilator prawdopodobnie utworzy ten sam kod maszynowy dla (bezużytecznego) specyfikatora „auto” jak dla „register ' specyficzny. Pozostaje więc tylko ograniczenie poziomu kodu źródłowego polegające na niemożności przyjęcia adresu. BTW, ta mała dyskusja doprowadziła mnie do znalezienia błędu w Netbeans; od mojej ostatniej aktualizacji domyślnie jest to łańcuch narzędzi g ++ w nowych projektach C!
GermanNerd

6

W języku C statyczny ma dwa znaczenia, w zależności od zakresu jego zastosowania. W zakresie globalnym, gdy obiekt jest deklarowany na poziomie pliku, oznacza to, że obiekt ten jest widoczny tylko w tym pliku.

W każdym innym zakresie deklaruje obiekt, który zachowa swoją wartość między różnymi momentami wprowadzenia danego zakresu. Na przykład jeśli int jest odwzorowywany w ramach procedury:

void procedure(void)
{
   static int i = 0;

   i++;
}

wartość „i” jest inicjowana do zera przy pierwszym wywołaniu procedury, a wartość jest zachowywana przy każdym kolejnym wywołaniu procedury. wydrukowanie „i” spowoduje wygenerowanie sekwencji 0, 1, 2, 3, ...


5

Należy zauważyć, że zmienne statyczne w funkcjach są inicjalizowane przy pierwszym wejściu do tej funkcji i zachowują się nawet po zakończeniu ich wywołania; w przypadku funkcji rekurencyjnych zmienna statyczna jest inicjalizowana tylko raz i utrzymuje się również we wszystkich wywołaniach rekurencyjnych, a nawet po zakończeniu wywołania funkcji.

Jeśli zmienna została utworzona poza funkcją, oznacza to, że programista może używać zmiennej tylko w pliku źródłowym, zmienna została zadeklarowana.


5

Jeśli zadeklarujesz to w mytest.cpliku:

static int my_variable;

Wówczas zmienną można zobaczyć tylko z tego pliku. Zmiennej nie można eksportować nigdzie indziej.

Jeśli zadeklarujesz wewnątrz funkcji, wartość zmiennej zachowa swoją wartość przy każdym wywołaniu funkcji.

Funkcji statycznej nie można wyeksportować spoza pliku. Tak więc w *.cpliku ukrywasz funkcje i zmienne, jeśli zadeklarujesz je jako statyczne.


4

Zmienne statyczne w C mają okres istnienia programu.

Jeśli są zdefiniowane w funkcji, mają zasięg lokalny, tzn. Można uzyskać do nich dostęp tylko wewnątrz tych funkcji. Wartość zmiennych statycznych jest zachowywana między wywołaniami funkcji.

Na przykład:

void function()
{
    static int var = 1;
    var++;
    printf("%d", var);
}

int main()
{
    function(); // Call 1
    function(); // Call 2
}

W powyższym programie varjest przechowywany w segmencie danych. Jego żywotność to cały program C.

Po wywołaniu funkcji 1 varstaje się 2. Po wywołaniu funkcji 2 varstaje się 3.

Wartość varnie jest niszczona między wywołaniami funkcji.

Gdyby varmiał zmienną niestatyczną i lokalną, byłby przechowywany w segmencie stosu w programie C. Ponieważ ramka stosu funkcji jest niszczona po powrocie funkcji, wartość parametru varjest również niszczona.

Zainicjowane zmienne statyczne są przechowywane w segmencie danych programu C, podczas gdy niezainicjowane zmienne są przechowywane w segmencie BSS.

Kolejna informacja o statyce: jeśli zmienna jest globalna i statyczna, ma czas życia programu C, ale ma zasięg pliku. Jest widoczny tylko w tym pliku.

Aby spróbować:

plik1.c

static int x;

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

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

Teraz spróbuj połączyć je za pomocą:

gcc -o output file1.o file2.o

Dałoby to błąd linkera, ponieważ x ma zakres pliku file1.c, a linker nie byłby w stanie rozpoznać odwołania do zmiennej x użytej w pliku2.c.

Bibliografia:

  1. http://en.wikipedia.org/wiki/Translation_unit_(programming)
  2. http://en.wikipedia.org/wiki/Call_stack

Rozumiem, że dane są trwałe, co oznacza, że ​​nie zostaną utracone po każdym wywołaniu funkcji, ale dlaczego nie static int var = 1;zmienia wartości z powrotem na jedną za każdym razem
Eames

3

Zmienna statyczna jest specjalną zmienną, której można użyć w funkcji, i zapisuje dane między połączeniami i nie usuwa ich między wywołaniami. Na przykład:

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();
    }
}

Wyjście:

0, 1, 2, 3, 4, 5, ...


Możesz zamienić na printf("%d, ", count); count++;`printf ("% d, ", count ++) (nie ma to znaczenia: P).
RastaJedi

2

Wartość zmiennej statycznej utrzymuje się między różnymi wywołaniami funkcji, a jej zakres jest ograniczony do bloku lokalnego, a zmienna statyczna zawsze inicjuje się wartością 0


2

Istnieją 2 przypadki:

(1) Zadeklarowane zmienne lokalne static: Przydzielone w segmencie danych zamiast stosu. Jego wartość zostaje zachowana po ponownym wywołaniu funkcji.

(2) Zadeklarowane zmienne globalne lub funkcje static: Niewidoczne poza jednostką kompilacji (tzn. Są lokalnymi symbolami w tablicy symboli podczas łączenia).


1

Zmienne statyczne mają tę właściwość, że zachowują swoją wartość nawet po przekroczeniu zakresu! W związku z tym zmienne statyczne zachowują swoją poprzednią wartość w poprzednim zakresie i nie są ponownie inicjowane w nowym zakresie.

Spójrz na to na przykład - statyczna zmienna int pozostaje w pamięci podczas działania programu. Zmienna normalna lub automatyczna jest niszczona po zakończeniu wywołania funkcji, w której zmienna została zadeklarowana.

#include<stdio.h> 
int fun() 
{ 
  static int count = 0; 
  count++; 
  return count; 
} 

int main() 
{ 
  printf("%d ", fun()); 
  printf("%d ", fun()); 
  return 0; 
}

To wygeneruje: 1 2

Gdy 1 pozostaje w pamięci, ponieważ została uznana za statyczną

Zmienne statyczne (takie jak zmienne globalne) są inicjowane jako 0, jeśli nie są jawnie inicjowane. Na przykład w poniższym programie wartość x jest drukowana jako 0, podczas gdy wartość y jest czymś śmieciowym. Zobacz to po więcej szczegółów.

#include <stdio.h> 
int main() 
{ 
    static int x; 
    int y; 
    printf("%d \n %d", x, y); 
}

Spowoduje to wyświetlenie: 0 [some_garbage_value]

Są to główne, które znalazłem, ale które nie zostały wyjaśnione powyżej dla początkujących!


-1

W programowaniu C staticjest zastrzeżonym słowem kluczowym, które kontroluje zarówno żywotność, jak i widoczność. Jeśli zadeklarujemy zmienną jako statyczną wewnątrz funkcji, będzie ona widoczna tylko w tej funkcji. W tym zastosowaniu czas życia tej zmiennej statycznej rozpocznie się, gdy wywołanie funkcji, i zniszczy się po wykonaniu tej funkcji. możesz zobaczyć następujący przykład:

#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; 
}

Powyższy program da nam ten wynik:

First Counter Output = 1 
Second Counter Output = 1 

Ponieważ jak tylko wywołamy funkcję, zainicjuje ona count = 0. A kiedy wykonamy counterFunction, zniszczy zmienną count.


2
> Powyższy program da nam ten wynik: Wyjście pierwszego licznika = 1 Wyjście drugiego licznika = 1 <Nieprawda. Zmienne statyczne są inicjalizowane tylko raz. Tak więc wynik będzie wynosił 1, a następnie 2 itd.
GermanNerd
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.