A palavra-chave externa em C

Este artigo demonstrará vários métodos sobre como usar a palavra-chave extern em C.

Use a palavra-chave extern para declarar uma variável definida em outros arquivos em C

Geralmente, as variáveis da linguagem C têm 3 tipos diferentes de vínculo: vínculo externo, vínculo interno ou sem vínculo. Se uma variável é definida em um bloco ou escopo de função, ela é considerada sem ligação. Uma variável que possui o escopo do arquivo pode ter ligação interna ou externa. Ou seja, se uma variável global é declarada com o qualificador static, ela tem a ligação interna, o que implica que a variável pode ser usada em um único arquivo de origem (unidade de tradução para ser mais preciso). Uma variável global sem um qualificador static é considerada como tendo ligação externa e pode ser usada em diferentes arquivos de origem. Para usar a variável global definida em algum outro arquivo de origem, ela deve ser declarada usando a palavra-chave extern.

#include <stdio.h>
#include <stdlib.h>

#ifndef COUNT
#define COUNT 10
#endif

extern int counter;

int main(void) {

    printf("counter: ");
    for (int i = 0; i < COUNT; ++i) {
        counter += 1;
        printf("%d, ", counter);
    }
    printf("\b\b \n");

    exit(EXIT_SUCCESS);
}

Resultado:

counter: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

Variáveis qualificadas extern geralmente são definidas em algum lugar em arquivos diferentes. Ainda assim, tecnicamente, pode-se declarar variáveis ​​globais no mesmo arquivo com a palavra-chave extern, conforme mostrado no exemplo a seguir. Esse tipo de declaração é essencialmente redundante porque o compilador torna automaticamente os nomes de variáveis ​​visíveis em qualquer lugar no mesmo escopo do arquivo.

#include <stdio.h>
#include <stdlib.h>

#ifndef COUNT
#define COUNT 10
#endif

int counter2 = 0;

int main(void) {

    extern int counter2; //redundant
    counter2 += 10;
    printf("%d\n", counter2);

    exit(EXIT_SUCCESS);
}

Lembre-se, porém, de que as variáveis ​​declaradas extern não devem ser inicializadas, pois isso leva a avisos do compilador se definirmos a variável global const char* em um arquivo de origem e a inicializarmos com algum valor literal de string. Declarar a mesma variável sem o qualificador const no arquivo de origem diferente compilará sem avisos e removerá a constância do objeto. Assim, se o usuário tentar modificar a string somente leitura tmp, o compilador não lançará um erro, mas o programa atingirá a falha de segmentação.

#include <stdio.h>
#include <stdlib.h>

#ifndef COUNT
#define COUNT 10
#endif

extern int counter;
//extern int counter = 3; // erroreous
extern char *tmp; // erroreous

int counter2 = 0;

int main(void) {

    printf("counter: ");
    for (int i = 0; i < COUNT; ++i) {
        counter += 1;
        printf("%d, ", counter);
    }
    printf("\b\b \n");

    tmp[0] = 'S'; // segmentation fault
    printf("%s", tmp);

    exit(EXIT_SUCCESS);
}