funkcja statyczna w C

Jaki jest sens tworzenia funkcji statycznej w C?

 159
Author: sarnold, 2011-03-16

6 answers

Tworzenie funkcji static ukrywa ją przed innymi jednostkami translacyjnymi, co pomaga zapewnićenkapsulację .

Helper_file.c

int f1(int);        /* prototype */
static int f2(int); /* prototype */

int f1(int foo) {
    return f2(foo); /* ok, f2 is in the same translation unit */
                    /* (basically same .c file) as f1         */
}

int f2(int foo) {
    return 42 + foo;
}

Main.c:

int f1(int); /* prototype */
int f2(int); /* prototype */

int main(void) {
    f1(10); /* ok, f1 is visible to the linker */
    f2(12); /* nope, f2 is not visible to the linker */
    return 0;
}
 201
Author: pmg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-16 23:42:02

Pmg {[4] } jest punktem na temat enkapsulacji; poza ukrywaniem funkcji przed innymi jednostkami tłumaczeniowymi (a raczej ponieważ ), tworzenie funkcji static może również przynieść korzyści wydajnościowe w obecności optymalizacji kompilatora.

Ponieważ funkcja static nie może być wywołana z dowolnego miejsca poza bieżącą jednostką tłumaczenia (chyba że kod pobiera wskaźnik do swojego adresu), kompilator kontroluje wszystkie punkty wywoławcze do niej.

Oznacza to, że jest wolny od Użyj niestandardowego ABI, wbuduj go w całości lub wykonaj dowolną liczbę innych optymalizacji, które mogą nie być możliwe dla funkcji z powiązaniem zewnętrznym.

 74
Author: Stephen Canon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-16 23:23:12

Słowo kluczowe static w języku C jest używane w skompilowanym pliku (.c w przeciwieństwie do .h) tak, że funkcja istnieje tylko w tym pliku.

Zwykle, gdy tworzysz funkcję, kompilator generuje cruft, którego linker może użyć do, cóż, połączenia wywołania funkcji z tą funkcją. Jeśli użyjesz słowa kluczowego static, inne funkcje w tym samym pliku mogą wywołać tę funkcję( ponieważ można to zrobić bez uciekania się do linkera), podczas gdy linker nie ma informacji pozwalających innym plikom uzyskać dostęp do funkcja.

 24
Author: 3Doubloons,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-15 23:51:33

Patrząc na posty powyżej chciałbym wskazać jeden szczegół.

Załóżmy, że nasz plik główny ("main.c") wygląda tak:

#include "header.h"

int main(void) {
    FunctionInHeader();
}

Rozważmy teraz trzy przypadki:

  • Przypadek 1: Nasz plik nagłówkowy ("header.h") wygląda tak:

    #include <stdio.h>
    
    static void FunctionInHeader();
    
    void FunctionInHeader() {
        printf("Calling function inside header\n");
    }
    

    Następnie następujące polecenie na Linuksie:

    gcc main.c header.h -o main
    

    Będzie sukces ! Po tym, jeśli ktoś działa

    ./main
    

    Wyjście będzie

    wywołanie funkcji wewnątrz nagłówka

    Czyli co to funkcja statyczna powinna zostać wydrukowana.

  • Przypadek 2: nasz plik nagłówkowy ("header.h") wygląda tak:

    static void FunctionInHeader();     
    

    I mamy jeszcze jeden nagłówek pliku".c", który wygląda tak:

    #include <stdio.h>
    
    #include "header.h"
    
    void FunctionInHeader() {
        printf("Calling function inside header\n");
    }
    

    Następnie następujące polecenie

    gcc main.c header.h header.c -o main
    

    Spowoduje błąd.

  • Przypadek 3:

    Podobne do przypadku 2, z tym, że teraz nasz plik nagłówkowy ("header.h") jest:

    void FunctionInHeader(); // keyword static removed
    

    Wtedy powiedzie się to samo polecenie, co w przypadku 2 i będzie dalej wykonywane ./ main da oczekiwany wynik.

Więc z tych testów (wykonanych na komputerze Acer x86, Ubuntu OS) założyłem, że

słowo kluczowe statyczne uniemożliwia zdefiniowanie funkcji w innym Pliku niż ten, w którym jest zadeklarowana.

Popraw mnie, jeśli się mylę.
 8
Author: mercury0114,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-30 02:36:30

Programiści C używają atrybutu statycznego do ukrywania deklaracji zmiennych i funkcji wewnątrz modułów, podobnie jak w przypadku publicznych i prywatnych deklaracji w Javie i C++. Pliki źródłowe C odgrywają rolę Moduły. Każda globalna zmienna lub funkcja zadeklarowana z atrybutem statycznym jest prywatna dla tego modułu. Podobnie każda globalna zmienna lub funkcja zadeklarowana bez atrybutu statycznego jest publiczna i może być dostęp przez dowolny inny moduł. Jest to dobra praktyka programowania, aby chronić swoje zmienne i funkcje z atrybutem statycznym w miarę możliwości.

 5
Author: Computer Systems,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-16 00:17:21

Odpowiedź Pmg jest bardzo przekonująca. Jeśli chcesz wiedzieć, jak działają deklaracje statyczne na poziomie obiektu, poniższe informacje mogą Cię zainteresować. Ponownie użyłem tego samego programu napisanego przez pmg i skompilowałem go do pliku. so(shared object)

Po wrzuceniu pliku. so do czegoś czytelnego dla człowieka

0000000000000675 f1: adres funkcji f1

0000000000068c f2: adres f2 (staticc) function

Zwróć uwagę na różnicę w adresie funkcji , to coś znaczy . Dla funkcji, która jest zadeklarowana z innym adresem, może to bardzo dobrze oznaczać, że f2 mieszka bardzo daleko lub w innym segmencie pliku obiektowego.

Łączniki używają czegoś o nazwie PLT (Procedure linkage table) I GOT (Global offsets table), aby zrozumieć symbole, do których mają dostęp.

Na razie pomyśl, że GOT i PLT magicznie wiążą wszystkie adresy i dynamiczny sekcja zawiera informacje o wszystkich tych funkcjach, które są widoczne przez linker.

Po zrzuceniu sekcji dynamicznej pliku. so otrzymujemy kilka wpisów, ale interesuje nas tylko funkcja f1 i f2.

Sekcja dynamiczna przechowuje wpis tylko dla F1 funkcji pod adresem 0000000000000675 i nie dla f2 !

Num: Wartość Rozmiar Typ Bind Vis NDX Nazwa

 9: 0000000000000675    23 FUNC    GLOBAL DEFAULT   11 f1

I to wszystko !. Z tego wynika, że linker nie będzie w stanie znaleźć funkcji f2 , ponieważ nie znajduje się ona w dynamicznej sekcji pliku .so.

 2
Author: human.js,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-30 04:00:41