Najlepsza odpowiedź
Ponieważ wiemy, że funkcje zdefiniowane w pliku mogą być dostępne w innym pliku. Jeśli chcemy ograniczyć możliwość wywoływania funkcji w innym pliku, możemy uczynić je statycznymi.
Stąd funkcje statyczne to te funkcje, które są wywoływalne w tym samym pliku, w którym definiują .
Możemy zdefiniować funkcję statyczną, używając następującej składni
static return\_type function\_name(arguments)
{
function\_body;
}
Oto funkcja znajdująca pierwiastek kwadratowy z podanej liczby
static long int getSquare(int num){
return (num*num);
}
Program demonstrujący przykład funkcji statycznej w języku C
#include
//static function definition
static long int getSquare(int num){
return (num*num);
}
int main()
{
int num;
printf("Enter an integer number: ");
scanf("\%d",&num);
printf("Square of \%d is \%ld.\n",num,getSquare(num));
return 0;
}
Wynik
Enter an integer number: 36
Square of 36 is 1296.
Dlaczego funkcje statyczne są wymagane?
Ponieważ funkcje służą do ponownego wykorzystania kodu (to znaczy kod, który napisałeś, może uzyskać dostęp do innego pliku, umieszczając go w funkcjach ), ale gdy chcesz zdefiniować jakieś funkcje, których nie można udostępniać (wywoływać) w innym pliku .
Funkcje statyczne są również pomocne przy obsłudze problemu z konfliktem deklaracji – jeśli w dwóch różnych plikach o tej samej nazwie znajdują się dwie funkcje, deklaracja funkcji spowoduje konflikt. Możemy uczynić je statycznymi.
Aby spełnić tego rodzaju wymagania, możemy uczynić je statycznymi .
Odpowiedź
Krótka odpowiedź: Oznacza to, że nazwa funkcji jest widoczna i możliwa do wywołania tylko w aktualnie kompilowanym pliku. Inne pliki skompilowane osobno nie będą widzieć nazwy funkcji ani nie będą w stanie jej wywołać. Następnie mogą mieć własne funkcje statyczne o tej samej nazwie. Pozwala to uniknąć kolizji nazw w dołączeniach plików oraz w linkowaniu plików obiektowych i bibliotek binarnych.
Istnieją 4 różne klasy pamięci do przechowywania w C.
- auto (automatyczne) to jest „zwykłe” (domyślne) i używa słowa kluczowego auto , ale tak zwykle nie jest określony, ponieważ jest domyślny
- register jest „wskazówką” dla kompilatora, że może zoptymalizować kod utworzony do przechowywania wartość w rejestrze procesora dla szybszego przetwarzania. Kompilator spróbuje, jeśli to możliwe, ale jeśli nie, to tak samo jak zwykły.
- extern zewnętrzny oznacza, że istnieje tylko jedna zmienna globalna o tej nazwie i wszystkie pliki deklarujące ją jako extern będą używać tej pamięci. Jeden plik zadeklaruje ją globalnie jako zwykłą zmienną, gdzie zostanie przydzielona podczas kompilacji.
- statyczny specyfikator pamięci w plikach źródłowych C oznacza kilka różnych rzeczy.
- Nazwa i pamięć nie są eksportowane do innych plików kompilowanych w tym samym czasie. Dzięki temu każdy plik może mieć identyczne nazwy, które nie kolidują.
- Pamięć utworzona dla zmiennej jest tworzona w obszarze pamięci statycznej i inicjowana na 0 przy uruchomieniu programu lub z jawną wartością.
- Inicjalizacja zmiennej statycznej jest wykonywana tylko raz . (w czasie kompilacji). Od tego czasu przypisane wartości są przechowywane przez cały czas trwania programu lub do czasu zmiany ich przez przypisanie.
- Pamięć statyczna zadeklarowana w funkcjach ma zasięg funkcji, ale statyczną alokację. Oznacza to, że pamięć jest trwała przez cały czas trwania programu i nie jest tworzona, gdy ramka stosu funkcji jest przydzielana dla wywołania funkcji. Zachowuje swoją wartość poprzez wiele wywołań funkcji. Pamięć zachowuje się, mimo że blok kodu jest odzyskiwany ze stosu po jego zwróceniu.
int accumulate( unsigned int x)
{
static unsigned int acc = 0;
acc = acc + x;
return acc;
}
- Powyższe zwróci bieżąca suma danych wejściowych, ponieważ zmienna acc zachowałaby wartość przez każde wywołanie. acc zostanie zainicjowany na 0 podczas ładowania programu.
- zmienne statyczne mają adresy w pamięci RAM i można je wysyłać do funkcji przez odniesienie lub wartość.
- Zmienne o mniejszym zakresie (zdefiniowane w funkcjach), które mają taką samą nazwę jak zmienna statyczna poza tym zakresem, przesłaniają zmienną statyczną, tak samo jak inne.
- zmienne statyczne nie mogą być eksportowane do plików zewnętrznych, więc wartości mogą zostać utracone w domenach kompilacji, jeśli nie zostaną jawnie wysłane jako parametry według wartości. (rozumiem!)
- Podobnie jak 4, inne pliki nie mają dostępu do zmiennych statycznych jako extern , tak jak w przypadku automatyczne (normalne) zmienne. To nie zadziała, otrzymasz błędne programy, które ulegną awarii, a kompilator może zostać oszukany i przeoczyć.
- Zmienne statyczne mogą być inicjowane w ich deklaracji, ale wartość inicjująca musi być wyrażeniem stałym, możliwym do oszacowania w czasie kompilacji, a nie wartość, której nie można obliczyć w czasie kompilacji. Nie można zainicjować zmiennej statycznej z nieznaną wartością, taką jak zmienna parametru, lub wynikiem wywołania funkcji, które nie wystąpiło w czasie kompilacji.
int accumulate( unsigned int x)
{
/* ERROR x is not a compile-time constant. */
static unsigned int acc = x;
static unsigned int acc = 0; /* OK */
acc = acc + x;
return acc;
}
Funkcje statyczne
- Funkcja statyczna w C ma zasięg pliku . Funkcja statyczna nie może być wywołane przez inny plik w tej samej jednostce tłumaczeniowej. Jednostka tłumacząca to cały kod źródłowy trafiający do kompilatora po wstępnym przetworzeniu w celu jednoczesnej kompilacji. Funkcje statyczne nie mogą uzyskiwać dostępu do zmiennych statycznych ani wywoływać funkcji statycznych z innych plików. Więc jeśli chcesz ograniczyć dostęp do funkcji do bieżącego pliku, możesz uczynić go statycznym. W tym pliku może istnieć tylko jedna funkcja o tej nazwie (która zachowuje się również dla zwykłych funkcji), więc często funkcje narzędziowe są umieszczane w plikach nagłówkowych w celu włączenia ich do wielu kompilacji, a nagłówek jest chroniony poleceniami preprocesora, aby nie być uwzględnione w dowolnej jednostce kompilacji więcej niż raz. Wszystkie standardowe nagłówki biblioteki C są pełne funkcji globalnych, a te są chronione, dzięki czemu są kompilowane tylko raz w kompilacji i są funkcjami globalnymi. Brak funkcji statycznych. Mówi się, że funkcje statyczne mają „wewnętrzne powiązanie” , co oznacza, że nie można ich zobaczyć w innych skompilowanych modułach, nawet jeśli są połączone z tym samym końcowym programem lub biblioteką. Jeśli funkcja nie jest statyczna , to w C ta funkcja jest funkcją globalną i będzie dostępna w całym programie globalnie. Oznacza to, że możesz mieć tylko jedną funkcję o nazwie print w całym programie . Aby obejść ten problem, ustaw swoje funkcje i zmienne jako statyczne, aby uniknąć konfliktu nazw.
- Funkcje są globalne i domyślnie zewnętrzne , z wyjątkiem pliku, w którym są zdefiniowane. Dlatego nie widzisz słowa extern używany w kodzie źródłowym C z funkcjami, ponieważ jest już tam niejawnie. Dlatego można wywołać normalne funkcje z dowolnego pliku w jednostce tłumaczeniowej. Mówi się, że mają zewnętrzny link , co oznacza, że po połączeniu są widoczne i wywoływalne przez dowolny plik w module lub dowolny inny moduł w połączonym programie.
- Deklaracja prototypu funkcji to „wstępna definicja”, czyli niejawnie zewnętrzna . Kod po przeskanowaniu deklaracji prototypu po raz pierwszy może wywołać funkcję, o ile pełna definicja istnieje w końcowym kodzie. Oznacza to, że „rzeczywista definicja” musi faktycznie istnieć, w przeciwnym razie faza łączenia zakończy się niepowodzeniem. Dlatego nagłówki w języku C zwykle nie zawierają kodu źródłowego funkcji, nie są potrzebne do kompilacji, ale znajdują się w fazie łączenia.
- Deklaracja prototypu funkcji statycznej jest „wstępną definicją”, która wyraźnie nie jest zewnętrzną . Pełna definicja musi znajdować się w bieżącej jednostce tłumaczeniowej (skompilowanej w tym samym czasie). W przeciwnym razie kompilacja się nie powiedzie. Nowoczesne kompilatory C zsyntetyzują prototyp z definicji, o ile występuje on wcześniej niż rzeczywiste wywołanie funkcji. Tak zwane „deklaracje do przodu” pozwalają na użycie wstępnych definicji z rzeczywistą definicją później i mają różne zastosowania w strukturach danych i organizacji bibliotek.
- Pierwsza definicja podpisu pliku jest używana dla całego programu, w tym statycznego lub zewnętrznego. Gdy funkcja jest zdefiniowana po raz pierwszy, jeśli jest zadeklarowana początkowo jako statyczna, zawsze będzie statyczna, nawet jeśli później zostanie przedefiniowana bez słowa kluczowego static. Jeśli początkowo zadeklarowano jako extern (domyślnie), nie można go przedefiniować jako statycznego.
static void f(int); /* Function is always static */
...
void f(int x) { ….} /* static , not exported, no error */
void f(int); /* Function is always global */
...
static void f(int x) { ….} /*ERROR NOT STATIC */
clang: "error: static declaration of "f" follows non-static declaration"
- Funkcje zdefiniowane w zakresie blokowym nie mogą być deklarowane jako statyczne. Tylko definicje funkcji statycznych w zakresie plików mogą być tworzone poza jakimkolwiek blokiem. Ma to sens z logicznego punktu widzenia, ponieważ zakres pliku nie może być mniejszy niż cały plik. Zdefiniuj więc funkcję statyczną lub przynajmniej prototyp bardzo wcześnie w pliku.
- Statyczne odnosi się do funkcji, a nie do typu zwracanego . Możesz umieścić statyczne słowo kluczowe po zwracanym typie, jeśli chcesz, ale jeśli to zrobisz, jesteś dziwny i zmylisz ludzi. Wartość zwracana nie jest statyczna, a funkcja jest.
- Statyczna definicja funkcji nie zastąpi globalny zdefiniowany przed nim w tym samym pliku lub w dołączonym pliku. Jeśli istnieje już zdefiniowana funkcja o tej nazwie, nie możesz przedefiniować jej za pomocą funkcji statycznej ani żadnej funkcji o tej samej nazwie.
C nie zmienia wewnętrznie nazw funkcji i zmiennych , jak robi to C ++, więc nie obsługuje przeciążania funkcji. C ++ „zamienia” nazwy funkcji z zakodowaną nazwą wskazującą na kilka dodatkowych rodzajów danych, na przykład czy jest to część klasy lub jakie są jej parametry itp. Tak więc w C bez słowa kluczowego static, możesz mieć tylko jedną funkcję każda unikalna nazwa w programie, bez względu na to, ile plików lub bibliotek to zawiera.
Więc co zrobić, jeśli chcesz zmienić swoją funkcję na już istniejącą wcześniej?
Cóż, sprytni programiści C wymyślają inną nazwę dla swojej funkcji. Ale jest sposób na „oszukanie” kompilatora przez zapobiegawczą zmianę tekstu źródłowego za pomocą preprocesora.
Przykład: Jakiś idiota napisał w swojej bibliotece funkcję int sort( char** Array)
i uczynił go globalnym, jest błędny i nie robi dokładnie tego, co chcesz, ponieważ sprawia, że liczby pojawiają się po literach lub czymś innym, a słowa T są zawsze pierwsze z jakiegoś powodu.
Chcesz użyj biblioteki, ale musisz naprawić funkcję, a masz tylko nagłówki i skompilowaną bibliotekę, a nie kod źródłowy.
OK> więc tworzony jest „specjalny” nagłówek, który zastępuje całe wystąpienie „ sort ”z„ bad\_sort ”w nagłówku, a następnie importuje kod i zastępuje wszystkie wystąpienia„ sort ”słowem„ good\_sort ”. „Good\_sort” jest w całości zdefiniowany w good\_sort.h, ale jest oznaczony jako statyczny, więc jest znany tylko w pliku, w którym jest zawarty.
/* good\_sort.h */
#ifndef \_GOOD\_SORT\_H
#define \_GOOD\_SORT\_H
static int good\_sort(char** Array)
{
... //code here
return numsorted;
}
#endif
Dodano nawias ochronny definicji, aby upewnić się, że nie zostanie uwzględniony dwukrotnie.
/*-----------------------------------*/
/* program.c */
#include "Trumpsort.h" /* The buggy library header */
...
#ifdef sort
#undef sort /* undefine the sort function name as reserved */
#define sort bad\_sort /* replace the name */
#include "good\_sort.h" /* your fixed version */
#endif
#define sort good\_sort /* replace the name in this file */
/* rest of file */
Trochę bzdury, ale chodzi o wywołanie twojej funkcji zamiast złego przez zmianę nazwy wysyłając go do „good\_sort” i nazywając go zamiast tego. (ale tylko w tym pliku – static ).