Jak poprawnie używać słowa kluczowego extern w C

Moje pytanie dotyczy tego, kiedy funkcja powinna być odwołana ze słowem kluczowym extern W C.

Nie wiem, kiedy to powinno być stosowane w praktyce. Ponieważ piszę program, wszystkie funkcje, których używam, są udostępniane za pośrednictwem plików nagłówkowych, które zawarłem. Dlaczego więc warto extern uzyskać dostęp do czegoś, co nie zostało ujawnione w pliku nagłówkowym?

Mogę myśleć o tym, jak extern działa nieprawidłowo, a jeśli tak, proszę poprawić ja.

Edit: czy powinieneś extern coś, gdy jest to domyślna deklaracja bez słowa kluczowego w pliku nagłówkowym?

 200
c
Author: Jonathan Leffler, 2009-01-30

10 answers

"extern" zmienia połączenie. Za pomocą słowa kluczowego zakłada się, że funkcja / zmienna będzie dostępna w innym miejscu, a rozdzielenie zostanie odroczone do linkera.

Istnieje różnica między "extern" na funkcjach i na zmiennych: na zmiennych nie tworzy instancji samej zmiennej, tzn. nie alokuje żadnej pamięci. Trzeba to zrobić gdzie indziej. Dlatego jest to ważne, jeśli chcesz zaimportować zmienną z innego miejsca. Dla funkcji, to tylko mówi kompilatorowi, że połączenie jest zewnętrzne. Ponieważ jest to wartość domyślna (używasz słowa kluczowego "static", aby wskazać, że funkcja nie jest związana za pomocą połączenia zewnętrznego), nie musisz jej używać jawnie.

 255
Author: bluebrother,
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-11-25 11:00:57

Extern mówi kompilatorowi, że dane te są gdzieś zdefiniowane i będą połączone z linkerem.

Z Pomocą odpowiedzi tutaj i rozmowy z kilkoma przyjaciółmi tutaj jest praktyczny przykład użycia extern .

Przykład 1 - aby pokazać pułapkę:

File stdio.h:

int errno;
/* other stuff...*/

myCFile1.c:
#include <stdio.h>

Code...

myCFile2.c:
#include <stdio.h>

Code...

If myCFile1.o i myCFile2.o są połączone, każdy z plików c ma oddzielne kopie errno . To jest ten sam problem errno powinno być dostępne we wszystkich połączonych plikach.

Przykład 2- poprawka.

File stdio.h:

extern int errno;
/* other stuff...*/

File stdio.c

int errno;

myCFile1.c:
#include <stdio.h>

Code...

myCFile2.c:
#include <stdio.h>

Code...

Teraz, jeśli oba myCFile1.o i MyCFile2.o są połączone za pomocą linkera oba będą wskazywać na to samo errno . W ten sposób rozwiązujemy implementację za pomocą extern .

 172
Author: lillq,
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
2017-11-13 15:49:02

Zostało już powiedziane, że słowo kluczowe extern jest zbędne dla funkcji.

Jeśli chodzi o zmienne współdzielone między jednostkami kompilacji, należy zadeklarować je w pliku nagłówkowym za pomocą słowa kluczowego extern, a następnie zdefiniować je w jednym pliku źródłowym, bez słowa kluczowego extern. Dla najlepszej praktyki plik źródłowy powinien być plikiem udostępniającym nazwę pliku nagłówkowego.

 26
Author: aib,
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-01-30 17:56:36

W C' extern ' jest implikowane dla prototypów funkcji, ponieważ prototyp deklaruje funkcję zdefiniowaną gdzie indziej. Innymi słowy, prototyp funkcji domyślnie ma połączenie zewnętrzne; użycie 'extern' jest w porządku, ale jest zbędne.

(jeśli wymagane jest statyczne połączenie, funkcja musi być zadeklarowana jako "statyczna" zarówno w jej prototypie, jak i nagłówku funkcji, a te powinny normalnie znajdować się w tym samym .plik c).

 14
Author: Steve Melnikoff,
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
2009-01-30 20:03:42

Wiele lat później odkrywam to pytanie. Po przeczytaniu każdej odpowiedzi i komentarzy, pomyślałem, że mógłbym wyjaśnić kilka szczegółów ... Może to być przydatne dla osób, które dostają się tutaj przez wyszukiwanie gogli.

Pytanie dotyczy używania funkcji" extern", więc zignoruję użycie" extern " ze zmiennymi globalnymi.

Zdefiniujmy 3 prototypy funkcji

//--------------------------------------
//Filename: "my_project.H"
extern int function_1(void);
static int function_2(void);
       int function_3(void);

Plik nagłówkowy może być używany przez główny kod źródłowy w następujący sposób

//--------------------------------------
//Filename: "my_project.C"
#include "my_project.H"

void main(void){
    int v1 = function_1();
    int v2 = function_2();
    int v3 = function_3();
}

int function_2(void) return 1234;

W celu skompilowania i link, musimy zdefiniować "function_2" w tym samym pliku kodu źródłowego, w którym wywołujemy tę funkcję. Dwie pozostałe funkcje mogą być zdefiniowane w innym kodzie źródłowym " .C " lub mogą znajdować się w dowolnym pliku binarnym (.OBJ,*.LIB,*.DLL), dla których możemy nie mieć kodu źródłowego.

Dołączmy ponownie nagłówek " my_project.H "w innym"*.C " plik, aby lepiej zrozumieć różnicę. W tym samym projekcie dodajemy następujące plik //--------------------------------------

//Filename: "my_big_project_splitted.C"
#include "my_project.H"

void old_main_test(void){
    int v1 = function_1();
    int v2 = function_2();
    int v3 = function_3();
}

int function_2(void) return 5678;

int function_1(void) return 12;
int function_3(void) return 34;

Ważne cechy, które należy zauważyć: Gdy funkcja jest zdefiniowana jako "statyczna" w pliku nagłówkowym, kompilator / linker musi znaleźć instancję funkcji o tej nazwie w każdym module, który używa tego pliku nagłówkowego.

Funkcja, która jest częścią biblioteki C, może być zastąpiona tylko w jednym module przez ponowne zdefiniowanie prototypu jako "statyczny" tylko w tym module. Na przykład zastąp dowolne wywołanie na "malloc" i "free", aby dodać wykrywanie wycieku pamięci cecha.

Specyfik "extern" nie jest tak naprawdę potrzebny dla funkcji. Gdy "static" nie jest znaleziony, zawsze przyjmuje się, że funkcja jest "extern".

Jednak "extern" nie jest domyślnym parametrem dla zmiennych. Zwykle każdy plik nagłówkowy, który definiuje zmienne, które mają być widoczne w wielu modułach, musi użyć "extern". Jedynym wyjątkiem byłoby, gdyby zagwarantowano, że plik nagłówkowy zostanie dołączony z jednego i tylko jednego modułu.

Wielu project managerów wymagałoby wtedy, aby taka zmienna była umieszczony na początku modułu, nie wewnątrz żadnego pliku nagłówkowego. Niektóre duże projekty, takie jak emulator gier wideo "Mame" wymagają nawet, aby taka zmienna pojawiała się tylko nad pierwszą funkcją wykorzystującą je.

 10
Author: Christian Gingras,
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-12-17 04:45:36

Bardzo dobry artykuł o słowie kluczowym extern wraz z przykładami: http://www.geeksforgeeks.org/understanding-extern-keyword-in-c/

Choć nie zgadzam się, że używanie extern w deklaracjach funkcji jest zbędne. To ma być ustawienie kompilatora. Dlatego zalecam użycie extern w deklaracjach funkcji, gdy jest to potrzebne.

 8
Author: tozak,
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-01-30 17:58:08

Jeśli każdy plik w twoim programie jest najpierw skompilowany do pliku obiektowego, to pliki obiektowe są ze sobą połączone, potrzebujesz extern. Mówi kompilatorowi " Ta funkcja istnieje, ale kod dla niej jest gdzie indziej. Nie panikuj."

 5
Author: Chris Lutz,
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
2009-01-30 18:18:58

Wszystkie deklaracje funkcji i zmiennych w plikach nagłówkowych powinny być extern.

Wyjątkami od tej reguły są funkcje wbudowane zdefiniowane w nagłówku oraz zmienne, które - choć zdefiniowane w nagłówku-będą musiały być lokalne dla jednostki tłumaczenia( pliku źródłowego, do którego nagłówek zostanie dołączony): powinny to być static.

W plikach źródłowych, extern nie powinno być używane dla funkcji i zmiennych zdefiniowanych w pliku. Wystarczy przedrostek local definitions z static i nie robić nic dla definicje współdzielone-domyślnie będą to symbole zewnętrzne.

Jedynym powodem użycia extern w ogóle w pliku źródłowym jest zadeklarowanie funkcji i zmiennych, które są zdefiniowane w innych plikach źródłowych i dla których nie podano pliku nagłówkowego.


Deklarowanie prototypów funkcji {[0] } jest w rzeczywistości niepotrzebne. Niektórzy nie lubią go, ponieważ po prostu marnuje przestrzeń i deklaracje funkcji mają już tendencję do przepełniania granic linii. Innym się to podoba, ponieważ w ten sposób funkcje i zmienne mogą być traktowane w ten sam sposób.

 4
Author: Christoph,
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
2009-01-30 21:59:45

Gdy masz tę funkcję zdefiniowaną w innej dll lub lib, tak że kompilator odsyła do linkera, aby ją znaleźć. Typowy przypadek dotyczy wywoływania funkcji z API systemu operacyjnego.

 2
Author: Otávio Décio,
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
2009-01-30 17:43:05

Funkcje faktycznie zdefiniowane w innych plikach źródłowych powinny być tylko zadeklarowane w nagłówkach. W tym przypadku należy użyć extern, Gdy deklaruje prototyp w nagłówku.

Przez większość czasu twoje funkcje będą jedną z następujących (bardziej jak najlepsza praktyka):

  • static (normalne funkcje, które nie są widoczne na zewnątrz .plik c)
  • static inline (inlines from .c lub .h pliki)
  • extern (deklaracja w nagłówkach z następny rodzaj (patrz poniżej))
  • [brak słów kluczowych] (normal funkcje, które mają być dostępne za pomocą deklaracje external)
 2
Author: Eduard - Gabriel Munteanu,
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
2009-01-30 18:01:25