Percebi que se eu declarar uma variável global várias vezes, o compilador nem emitirá um aviso.
No entanto, se eu declarar uma variável local em uma função várias vezes, por exemplo, o compilador gcc gera um erro e não compila o arquivo. (Eu pergunto em termos de gcc, mas essa é mais uma questão geral de design de linguagem, não uma questão sobre gcc, porque acho que provavelmente outros compiladores se comportam de maneira semelhante).
Qual a explicação para esse comportamento?
extern int x;
, que é uma declaração, a compilação será interrompida, pois não há lugar onde a memória seja alocada para a variável.Respostas:
De acordo com as diretrizes de codificação :
A variável local não tem ligação. então existe um nome Colisão ocorre. Portanto, várias declarações da variável local não são possíveis.
A variável global possui ligação externa. Portanto, várias declarações de variáveis globais são possíveis.
fonte
O @msc fornece uma boa introdução às regras por trás desse comportamento.
C tem três tipos de declarações globais para objetos, a saber, aquelas que são (e eu estou comentando
static
aqui):extern int a;
int a = 3;
ouextern int a = 3;
int a;
Múltiplas declarações do tipo 1 e 3 são permitidas, enquanto no máximo uma definição (do tipo 2) é permitida.
Se você também está perguntando sobre a motivação dessas regras, é o suporte para compilação separada . (Ver unidade de tradução ).
Para dividir um programa em vários arquivos compilados separadamente, precisamos de alguns recursos, a saber: (a) poder declarar sem necessariamente definir e (b) declaração direta .
Dentro de uma unidade de tradução, precisamos nos referir a funções e dados globais em outra unidade de tradução. E também gostaríamos de uma verificação de erro, aqui, para descobrir definições ausentes e definições duplicadas erradas.
Às vezes, na mesma unidade de tradução, declaramos um global e o definimos mais tarde. Isso pode acontecer se precisarmos de uma declaração direta por algum motivo, ou se usarmos um arquivo de cabeçalho comum (que fornece declarações) dentro de uma unidade de tradução que também oferece definições explícitas.
Como a compilação separada em C se aplica ao vincular funções e dados globais, esses recursos são necessários no nível global, mas não no nível local.
Como o @msc aponta, nada disso é necessário para variáveis locais, pois elas não têm ligação.
C (como muitos outros idiomas) não fornece ligação para variáveis locais, pois o idioma não tenta suportar uma única função que abrange várias unidades de tradução separadas.
(Obviamente, você pode ter uma função em vários arquivos de origem, mas não em várias unidades de tradução.)
Uma definição provisória funciona como uma declaração, pois é permitida em várias unidades de tradução (e também combina bem com outras declarações). No entanto, se não houver uma definição (não tentativa) para o identificador em todo o programa, o conjunto de (uma ou mais) definições tentativas em várias unidades de conversão (para um identificador) será usado como uma definição para o objeto cujo inicializador é zero.
Isso pode ser implementado colocando-os na seção .BSS com o tamanho e o alinhamento adequados; o vinculador os corresponderá à definição verdadeira, se encontrado, ou corresponderá um ao outro, dando a eles espaço zerado no BSS.
A noção de compilação separada pode ser totalmente suportada sem o recurso de definições provisórias - acho que as definições provisórias existem principalmente por razões históricas. (Não estou dizendo que eles não são úteis, apenas se o idioma foi criado hoje, isso pode ser visto como desnecessário e, portanto, não ser oferecido.)
fonte