Wiele lat później odkrywam to pytanie. Po przeczytaniu każdej odpowiedzi i komentarza pomyślałem, że mogę wyjaśnić kilka szczegółów ... Może to być przydatne dla osób, które docierają tutaj za pomocą wyszukiwarki Google.
Pytanie dotyczy konkretnie użycia 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łówka 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;
Aby skompilować i połączyć, 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órego możemy nie mieć kodu źródłowego.
Dołączmy ponownie nagłówek „my_project.H” do innego pliku „* .C”, aby lepiej zrozumieć różnicę. W tym samym projekcie dodajemy następujący 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 funkcje, na które należy zwrócić uwagę:
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.
Funkcję, która jest częścią biblioteki C, można zastąpić tylko w jednym module, ponownie definiując prototyp na „statyczny” tylko w tym module. Na przykład zamień każde wywołanie na „malloc” i „free”, aby dodać funkcję wykrywania wycieków pamięci.
Specyfikator „extern” nie jest tak naprawdę potrzebny dla funkcji. Gdy „statyczny” nie zostanie znaleziony, zawsze przyjmuje się, że funkcja jest „zewnętrzna”.
Jednak „zewnętrzny” nie jest domyślny dla zmiennych. Zwykle każdy plik nagłówkowy, który definiuje zmienne widoczne w wielu modułach, musi używać „extern”. Jedynym wyjątkiem byłby przypadek, gdyby plik nagłówkowy był gwarantowany z jednego i tylko jednego modułu.
Wielu menedżerów projektów wymagałoby wtedy umieszczenia takiej zmiennej na początku modułu, a nie w żadnym pliku nagłówka. Niektóre duże projekty, takie jak emulator gier wideo „Mame”, wymagają nawet, aby taka zmienna pojawiała się tylko nad pierwszą funkcją, która ich używa.