Você precisa distinguir entre dois conceitos separados: definição de função e declaração de símbolo. "extern" é um modificador de ligação, uma dica para o compilador sobre onde o símbolo referido posteriormente é definido (a dica é "não aqui").
Se eu escrever
extern int i;
no escopo do arquivo (fora de um bloco de função) em um arquivo C, você está dizendo "a variável pode ser definida em outro lugar".
extern int f() {return 0;}
é uma declaração da função f e uma definição da função f. A definição neste caso substitui o externo.
extern int f();
int f() {return 0;}
é primeiro uma declaração, seguida pela definição.
O uso de extern
está errado se você deseja declarar e definir simultaneamente uma variável de escopo do arquivo. Por exemplo,
extern int i = 4;
dará um erro ou aviso, dependendo do compilador.
O uso de extern
é útil se você desejar explicitamente evitar a definição de uma variável.
Deixe-me explicar:
Digamos que o arquivo ac contenha:
#include "a.h"
int i = 2;
int f() { i++; return i;}
O arquivo ah inclui:
extern int i;
int f(void);
e o arquivo bc contém:
#include <stdio.h>
#include "a.h"
int main(void){
printf("%d\n", f());
return 0;
}
O externo no cabeçalho é útil, porque informa ao compilador durante a fase do link "esta é uma declaração e não uma definição". Se eu remover a linha em ac que define i, alocar espaço para ela e atribuir um valor a ela, o programa falhará ao compilar com uma referência indefinida. Isso informa ao desenvolvedor que ele se referiu a uma variável, mas ainda não a definiu. Se, por outro lado, eu omito a palavra-chave "extern" e removo a int i = 2
linha, o programa ainda compila - eu será definido com o valor padrão 0.
As variáveis de escopo do arquivo são definidas implicitamente com um valor padrão de 0 ou NULL se você não atribuir explicitamente um valor a elas - diferentemente das variáveis de escopo de bloco que você declara na parte superior de uma função. A palavra-chave extern evita essa definição implícita e, assim, ajuda a evitar erros.
Para funções, nas declarações de função, a palavra-chave é realmente redundante. As declarações de função não têm uma definição implícita.