Minha pergunta é sobre quando uma função deve ser referenciada com a extern
palavra - chave em C.
Não estou conseguindo ver quando isso deve ser usado na prática. Enquanto escrevo um programa, todas as funções que utilizo são disponibilizadas através dos arquivos de cabeçalho que incluí. Então, por que seria útil extern
obter acesso a algo que não foi exposto no arquivo de cabeçalho?
Eu poderia estar pensando em como extern
funciona incorretamente e, se sim, por favor me corrija.
Edit: Você deve extern
algo quando é a declaração padrão sem a palavra-chave em um arquivo de cabeçalho?
Respostas:
"
extern
" altera a ligação. Com a palavra-chave, supõe-se que a função / variável esteja disponível em outro lugar e a resolução seja adiada para o vinculador.Há uma diferença entre "extern" nas funções e nas variáveis: nas variáveis, ela não instancia a própria variável, ou seja, não aloca nenhuma memória. Isso precisa ser feito em outro lugar. Portanto, é importante se você deseja importar a variável de outro lugar. Para funções, isso apenas informa ao compilador que a ligação é externa. Como esse é o padrão (você usa a palavra-chave "estática" para indicar que uma função não está vinculada usando ligação externa), não é necessário usá-la explicitamente.
fonte
extern informa ao compilador que esses dados estão definidos em algum lugar e serão conectados ao vinculador.
Com a ajuda das respostas aqui e conversando com alguns amigos, aqui está o exemplo prático de um uso externo .
Exemplo 1 - para mostrar uma armadilha:
Se myCFile1.o e myCFile2.o estiverem vinculados, cada um dos arquivos c terá cópias separadas de errno . Esse é um problema, pois o mesmo erro está disponível em todos os arquivos vinculados.
Exemplo 2 - A correção.
Agora, se myCFile1.o e MyCFile2.o estiverem vinculados pelo vinculador, ambos apontarão para o mesmo erro . Assim, resolvendo a implementação com extern .
fonte
-Wall
e-pedantic
. Por quê ? e como ?Já foi declarado que a
extern
palavra-chave é redundante para funções.Quanto às variáveis compartilhadas entre as unidades de compilação, declare-as em um arquivo de cabeçalho com a palavra-chave extern e, em seguida, defina-as em um único arquivo de origem, sem a palavra-chave extern. O arquivo de origem único deve ser o único que compartilha o nome do arquivo de cabeçalho, para práticas recomendadas.
fonte
Muitos anos depois, descubro essa pergunta. Depois de ler todas as respostas e comentários, pensei em esclarecer alguns detalhes ... Isso pode ser útil para as pessoas que chegam aqui através da pesquisa no Google.
A questão é especificamente sobre o uso de funções "externas", portanto ignorarei o uso de "externas" com variáveis globais.
Vamos definir 3 protótipos de função:
O arquivo de cabeçalho pode ser usado pelo código fonte principal da seguinte maneira:
Para compilar e vincular, devemos definir "function_2" no mesmo arquivo de código-fonte em que chamamos essa função. As duas outras funções podem ser definidas em código-fonte diferente " .C" ou podem estar localizadas em qualquer arquivo binário ( .OBJ, * .LIB, * .DLL), para o qual talvez não tenhamos o código-fonte.
Vamos incluir novamente o cabeçalho "my_project.H" em um arquivo "* .C" diferente para entender melhor a diferença. No mesmo projeto, adicionamos o seguinte arquivo:
Recursos importantes a serem observados:
Quando uma função é definida como "estática" em um arquivo de cabeçalho, o compilador / vinculador deve encontrar uma instância de uma função com esse nome em cada módulo que usa esse arquivo de inclusão.
Uma função que faz parte da biblioteca C pode ser substituída em apenas um módulo, redefinindo um protótipo com "estático" apenas nesse módulo. Por exemplo, substitua qualquer chamada para "malloc" e "free" para adicionar o recurso de detecção de vazamento de memória.
O especificador "extern" não é realmente necessário para funções. Quando "estático" não é encontrado, sempre se assume que uma função é "externa".
No entanto, "extern" não é o padrão para variáveis. Normalmente, qualquer arquivo de cabeçalho que define variáveis a serem visíveis em muitos módulos precisa usar "extern". A única exceção seria se um arquivo de cabeçalho fosse garantido para ser incluído em um e apenas um módulo.
Muitos gerentes de projeto exigiriam que essa variável fosse colocada no início do módulo, não dentro de nenhum arquivo de cabeçalho. Alguns projetos grandes, como o emulador de videogame "Mame", exigem que essa variável apareça apenas acima da primeira função que os utiliza.
fonte
Em C, 'extern' é implícito para protótipos de funções, pois um protótipo declara uma função que é definida em outro lugar. Em outras palavras, um protótipo de função possui ligação externa por padrão; usar 'extern' é bom, mas é redundante.
(Se a vinculação estática for necessária, a função deve ser declarada como 'estática', tanto no protótipo quanto no cabeçalho da função, e esses normalmente devem estar no mesmo arquivo.
fonte
Um artigo muito bom sobre a
extern
palavra - chave, juntamente com os exemplos: http://www.geeksforgeeks.org/understanding-extern-keyword-in-c/Embora eu não concorde que o uso de
extern
declarações de função seja redundante. Supõe-se que seja uma configuração do compilador. Portanto, recomendo usar asextern
declarações de função quando necessário.fonte
Se cada arquivo em seu programa for compilado primeiro em um arquivo de objeto, então os arquivos de objeto serão vinculados
extern
. Diz ao compilador "Esta função existe, mas o código para ela está em outro lugar. Não entre em pânico."fonte
Todas as declarações de funções e variáveis nos arquivos de cabeçalho devem ser
extern
.Exceções a esta regra são funções embutidas definidas no cabeçalho e variáveis que - embora definidas no cabeçalho - terão que ser locais para a unidade de tradução (o arquivo de origem no qual o cabeçalho é incluído): essas devem ser
static
.Nos arquivos de origem,
extern
não deve ser usado para funções e variáveis definidas no arquivo. Prefixe as definições locais comstatic
e não faça nada para as definições compartilhadas - elas serão símbolos externos por padrão.O único motivo para usar
extern
em um arquivo de origem é declarar funções e variáveis definidas em outros arquivos de origem e para as quais nenhum arquivo de cabeçalho é fornecido.Declarar protótipos de funções
extern
é realmente desnecessário. Algumas pessoas não gostam disso porque apenas desperdiçam espaço e as declarações de função já tendem a ultrapassar os limites de linha. Outros gostam porque, dessa maneira, funções e variáveis podem ser tratadas da mesma maneira.fonte
extern
é opcional para declarações de função, mas eu gosto de tratar variáveis e funções da mesma maneira - pelo menos, é a coisa mais razoável que eu poderia ter, pois não me lembro exatamente por que comecei a fazer isso;)As funções realmente definidas em outros arquivos de origem devem ser declaradas apenas nos cabeçalhos. Nesse caso, você deve usar extern ao declarar o protótipo em um cabeçalho.
Na maioria das vezes, suas funções serão uma das seguintes (mais como uma prática recomendada):
fonte
Quando você tem essa função definida em uma DLL ou lib diferente, para que o compilador adie ao vinculador para encontrá-lo. Caso típico é quando você está chamando funções da API do SO.
fonte