Musisz rozróżnić dwie odrębne koncepcje: definicję funkcji i deklarację symbolu. „extern” to modyfikator linkowania, wskazówka dla kompilatora o tym, gdzie zdefiniowany jest symbol, do którego odwołuje się później (wskazówka brzmi „nie tutaj”).
Jeśli napiszę
extern int i;
w zakresie pliku (poza blokiem funkcyjnym) w pliku C, wtedy mówisz „zmienna może być zdefiniowana gdzie indziej”.
extern int f() {return 0;}
jest zarówno deklaracją funkcji f, jak i definicją funkcji f. Definicja w tym przypadku jest ważniejsza od zewnętrznej.
extern int f();
int f() {return 0;}
to najpierw deklaracja, po której następuje definicja.
Użycie opcji extern
jest niewłaściwe, jeśli chcesz zadeklarować i jednocześnie zdefiniować zmienną o zasięgu pliku. Na przykład,
extern int i = 4;
poda błąd lub ostrzeżenie, w zależności od kompilatora.
Użycie opcji extern
jest przydatne, jeśli jawnie chcesz uniknąć definicji zmiennej.
Pozwól mi wyjaśnić:
Powiedzmy, że plik ac zawiera:
#include "a.h"
int i = 2;
int f() { i++; return i;}
Plik ah zawiera:
extern int i;
int f(void);
a plik bc zawiera:
#include <stdio.h>
#include "a.h"
int main(void){
printf("%d\n", f());
return 0;
}
Extern w nagłówku jest przydatny, ponieważ informuje kompilator podczas fazy łączenia, że „to jest deklaracja, a nie definicja”. Jeśli usunę wiersz w ac, który definiuje i, przydzieli dla niego miejsce i przypisze mu wartość, program nie powinien się skompilować z niezdefiniowanym odniesieniem. To informuje dewelopera, że odniósł się do zmiennej, ale jeszcze jej nie zdefiniował. Jeśli z drugiej strony pominę słowo kluczowe „extern” i usunę int i = 2
wiersz, program nadal się kompiluje - i zostanie zdefiniowany z domyślną wartością 0.
Zmienne zakresu pliku są niejawnie definiowane z wartością domyślną 0 lub NULL, jeśli nie przypiszesz do nich jawnie wartości - w przeciwieństwie do zmiennych o zakresie blokowym, które deklarujesz na początku funkcji. Słowo kluczowe extern pozwala uniknąć tej niejawnej definicji, a tym samym pomaga uniknąć błędów.
W przypadku funkcji w deklaracjach funkcji słowo kluczowe jest rzeczywiście zbędne. Deklaracje funkcji nie mają niejawnej definicji.