Compartilhar via


Especificadores de classe de armazenamento para declarações de nível externo

As variáveis externas são variáveis no escopo de arquivo. São definidas fora de qualquer função, e estão potencialmente disponíveis para muitas funções. As funções só podem ser definidas no nível externo e, consequentemente, não podem ser aninhadas. Por padrão, todas as referências a variáveis externas e a funções do mesmo nome são referências ao mesmo objeto, o que significa que elas possuem vinculação externa. (Você pode usar a palavra-chave static para substituir esse comportamento).

As declarações de variáveis no nível externo são definições de variáveis (declarações de definição) ou referências a variáveis definidas em outro lugar (declarações de referência).

Uma declaração de variável externa que também inicializa a variável (implícita ou explicitamente) é uma declaração de definição da variável. Uma definição no nível externo pode ter diversos formatos:

  • Uma variável declarada com o especificador de classe de armazenamento static. Você pode inicializar explicitamente a variável static com uma expressão de constante, como descrito em Inicialização. Se você omitir o inicializador, a variável será inicializado com 0 por padrão. Por exemplo, essas duas instruções são consideradas definições da variável k.

    static int k = 16;
    static int k;
    
  • Uma variável inicializada explicitamente no nível externo. Por exemplo, int j = 3; é uma definição da variável j.

Em declarações de variável no nível externo (ou seja, fora de todas as funções), você pode usar o especificador de classe de armazenamento static ou extern ou omitir totalmente esse especificador. Você não pode usar os terminais auto e registerstorage-class-specifier no nível externo.

Depois que uma variável é definida no nível externo, ela é visível durante o resto da unidade de tradução. A variável não é visível antes de sua declaração no mesmo arquivo de origem. Além disso, ela não é visível em outros arquivos de origem do programa, a menos que uma declaração de referência torne-a visível, como descrito a seguir.

As regras relativas a static incluem:

  • Variáveis declaradas fora de todos os blocos sem a palavra-chave static sempre mantêm os valores em todo o programa. Para restringir o acesso a uma unidade de tradução específica, você deve usar a palavra-chave static. Isso dá a elas vinculação interna. Para torná-las globais a todo um programa, omita a classe de armazenamento explícita ou use a palavra-chave extern (consulte as regras na lista a seguir). Isso dá a elas vinculação externa. As vinculações interna e externa também são discutidas em Vinculação.

  • Você pode definir uma variável no nível externo apenas uma vez em um programa. Você pode definir outra variável com o mesmo nome e o especificador de classe de armazenamento static em uma unidade de tradução diferente. Como cada definição de static só é visível em sua própria unidade de tradução, não ocorre qualquer conflito. Isso oferece uma forma útil de ocultar nomes de identificadores que devem ser compartilhados entre funções de uma única unidade de tradução, mas não devem ser visíveis para outras unidades.

  • O especificador de classe de armazenamento static pode ser aplicado também a funções. Se você declarar uma função static, o nome será invisível fora do arquivo no qual ela foi declarada.

As regras para usar extern são:

  • O especificador de classe de armazenamento extern declara uma referência a uma variável definida em outro lugar. Você pode usar uma declaração extern para tornar visível uma definição em outro arquivo de origem, ou para tornar uma variável visível antes da sua definição no mesmo arquivo de origem. Depois que você tiver declarado uma referência à variável no nível externo, a variável ficará visível durante todo o restante da unidade de tradução na qual a referência declarada ocorre.

  • Para que uma referência extern seja válida, a variável à qual ela faz referência deve ser definida apenas uma vez no nível externo. Essa definição (sem a classe de armazenamento extern) pode ocorrer em qualquer das unidades de tradução que compõem o programa.

Exemplo

O exemplo a seguir ilustra declarações externas:

/******************************************************************
                      SOURCE FILE ONE
*******************************************************************/
#include <stdio.h>

extern int i;                // Reference to i, defined below
extern void other ( void );  // Reference to other(), defined in second source file
void next( void );           // Function prototype

int main()
{
    i++;
    printf_s( "%d\n", i );   // i equals 4
    next();
}

int i = 3;                  // Definition of i

void next( void )
{
    i++;
    printf_s( "%d\n", i );  // i equals 5
    other();
}

/******************************************************************
                      SOURCE FILE TWO
*******************************************************************/
#include <stdio.h>

extern int i;              // Reference to i in
                           // first source file
void other( void )
{
    i++;
    printf_s( "%d\n", i ); // i equals 6
}

Os dois arquivos de origem neste exemplo contêm um total de três declarações externas de i. Apenas uma das declarações é uma "declaração de definição". Essa declaração

int i = 3;

define a variável global i e a inicializa com valor inicial de 3. A declaração "de referência" i no topo do primeiro arquivo de origem que usa extern torna a variável global visível antes de sua declaração de definição no arquivo. A declaração de referência de i no segundo arquivo de origem também torna a variável visível no arquivo de origem. Se uma instância de definição para uma variável não for fornecida na unidade de tradução, o compilador presume que existe uma

extern int x;

declaração de referência que uma referência de definição

int x = 0;

aparece em outra unidade de tradução do programa.

Todas as três funções, main, next, e other, executadas na mesma tarefa: aumentam i e a imprimem. Os valores 4, 5 e 6, são impressos.

Se a variável i não tivesse sido inicializada, ela será definida automaticamente como 0. Nesse caso, os valores 1, 2, e 3 seriam impressos. Consulte Inicialização para obter mais informações sobre inicialização de variáveis.

Confira também

Classes de armazenamento C