È necessario distinguere tra due concetti separati: definizione della funzione e dichiarazione dei simboli. "extern" è un modificatore di collegamento, un suggerimento per il compilatore su dove viene definito il simbolo a cui si fa riferimento in seguito (il suggerimento è "non qui").
Se scrivo
extern int i;
nell'ambito del file (al di fuori di un blocco funzione) in un file C, quindi stai dicendo "la variabile può essere definita altrove".
extern int f() {return 0;}
è sia una dichiarazione della funzione f che una definizione della funzione f. La definizione in questo caso sovrascrive l'esterno.
extern int f();
int f() {return 0;}
è prima una dichiarazione, seguita dalla definizione.
L'uso di extern
è errato se si desidera dichiarare e contemporaneamente definire una variabile dell'ambito del file. Per esempio,
extern int i = 4;
fornirà un errore o un avviso, a seconda del compilatore.
L'uso di extern
è utile se si desidera evitare esplicitamente la definizione di una variabile.
Lasciatemi spiegare:
Supponiamo che il file ac contenga:
#include "a.h"
int i = 2;
int f() { i++; return i;}
Il file ah include:
extern int i;
int f(void);
e il file bc contiene:
#include <stdio.h>
#include "a.h"
int main(void){
printf("%d\n", f());
return 0;
}
L'esterno nell'intestazione è utile perché dice al compilatore durante la fase di collegamento "questa è una dichiarazione e non una definizione". Se rimuovo la linea in ac che definisce i, alloca spazio per essa e gli assegna un valore, il programma non dovrebbe compilare con un riferimento indefinito. Questo dice allo sviluppatore che ha fatto riferimento a una variabile, ma non l'ha ancora definita. Se, d'altra parte, ometto la parola chiave "extern" e rimuovo la int i = 2
riga, il programma si compila ancora - sarò definito con un valore predefinito di 0.
Le variabili dell'ambito del file vengono definite in modo implicito con un valore predefinito pari a 0 o NULL se non si assegna loro esplicitamente un valore, diversamente dalle variabili dell'ambito del blocco dichiarate all'inizio di una funzione. La parola chiave extern evita questa definizione implicita e quindi aiuta a evitare errori.
Per le funzioni, nelle dichiarazioni di funzioni, la parola chiave è effettivamente ridondante. Le dichiarazioni di funzione non hanno una definizione implicita.