extern (C++)

A palavra-chave extern pode ser aplicada a uma variável global, função ou declaração de modelo. Ele especifica que o símbolo tem externvinculação al. Para obter informações em segundo plano sobre a vinculação e por que o uso de variáveis globais é desencorajado, consulte Unidades de tradução e vinculação.

A palavra-chave extern tem quatro significados dependendo do contexto:

  • Em uma declaração de variável global não const, extern especifica que a variável ou função é definida em outra unidade de tradução. O extern deve ser aplicado em todos os arquivos, exceto aquele em que a variável está definida.

  • Em uma declaração de variável const, ela especifica que a variável tem vinculação external. extern deve ser aplicado a todas as declarações em todos os arquivos. (Variáveis const globais têm vinculação interna por padrão.)

  • extern "C" especifica que a função é definida em outro lugar e usa a convenção de chamada de linguagem C. O modificador extern "C" também pode ser aplicado a várias declarações de função em um bloco.

  • Em uma declaração de modelo, extern especifica que o modelo já foi instanciado em outro lugar. extern informa ao compilador que ele pode reutilizar a outra instância, em vez de criar uma nova no local atual. Para obter mais informações sobre esse uso de extern, consulte Instanciação explícita.

extern vinculação para não const globais

Quando o vinculador vê extern antes de uma declaração de variável global, ele procura a definição em outra unidade de tradução. As declarações de variáveis não const no escopo global são external por padrão. Aplica extern somente às declarações que não fornecem a definição.

//fileA.cpp
int i = 42; // declaration and definition

//fileB.cpp
extern int i;  // declaration only. same as i in FileA

//fileC.cpp
extern int i;  // declaration only. same as i in FileA

//fileD.cpp
int i = 43; // LNK2005! 'i' already has a definition.
extern int i = 43; // same error (extern is ignored on definitions)

extern vinculação para const globais

Uma variável global const têm vinculação interna por padrão. Se você quiser que a variável tenha vinculação external, aplique a palavra-chave extern à definição e a todas as outras declarações em outros arquivos:

//fileA.cpp
extern const int i = 42; // extern const definition

//fileB.cpp
extern const int i;  // declaration only. same as i in FileA

Vinculação de extern constexpr

No Visual Studio 2017 versão 15.3 e anteriores, o compilador sempre forneceu uma ligação interna variável constexpr, mesmo quando a variável era marcada como extern. No Visual Studio 2017 versão 15.5 e posteriores, o compilador /Zc:externConstexpr habilita o comportamento correto e em conformidade com os padrões. Em algum momento, isso se tornará o padrão. A opção /permissive- não habilita /Zc:externConstexpr.

extern constexpr int x = 10; //error LNK2005: "int const x" already defined

Se um arquivo de cabeçalho contiver uma variável declarada externconstexpr, ele precisará ser marcado como __declspec(selectany) para que suas declarações duplicadas sejam combinadas corretamente:

extern constexpr __declspec(selectany) int x = 10;

extern "C" e declaração da função extern "C++"

Em C++, quando usada com uma cadeia de caracteres, extern especifica que as convenções de vinculação de outra linguagem estão sendo usadas para os declaradores. As funções C e os dados podem ser acessados somente se forem declarados anteriormente como tendo vinculação C. No entanto, devem ser definidos em uma unidade de conversão compilada separadamente.

O Microsoft C++ oferece suporte às cadeias de caracteres "C" e "C++" no campo string-literal. Todos os arquivos de inclusão padrão usam a sintaxe extern "C" para permitir que funções da biblioteca em tempo de execução sejam usadas em programas C++.

Exemplo

O exemplo a seguir mostra como declarar os nomes que têm vinculação C:

// Declare printf with C linkage.
extern "C" int printf(const char *fmt, ...);

//  Cause everything in the specified
//  header files to have C linkage.
extern "C" {
    // add your #include statements here
#include <stdio.h>
}

//  Declare the two functions ShowChar
//  and GetChar with C linkage.
extern "C" {
    char ShowChar(char ch);
    char GetChar(void);
}

//  Define the two functions
//  ShowChar and GetChar with C linkage.
extern "C" char ShowChar(char ch) {
    putchar(ch);
    return ch;
}

extern "C" char GetChar(void) {
    char ch;
    ch = getchar();
    return ch;
}

// Declare a global variable, errno, with C linkage.
extern "C" int errno;

Se uma função tem mais de uma especificação de vinculação, elas devem ser correspondentes. É um erro declarar as funções como tendo vinculação C e C++. Além disso, se duas declarações para uma função ocorrem em um programa — uma com uma especificação de vinculação e a outra sem — a declaração com a especificação de vinculação deve ser a primeira. Todas as declarações redundantes de funções que já têm a especificação de vinculação são atribuídas a uma vinculação especificada na primeira declaração. Por exemplo:

extern "C" int CFunc1();
...
int CFunc1();            // Redeclaration is benign; C linkage is
                         //  retained.

int CFunc2();
...
extern "C" int CFunc2(); // Error: not the first declaration of
                         //  CFunc2;  cannot contain linkage
                         //  specifier.

A partir do Visual Studio 2019, quando /permissive- é especificado, o compilador verifica se as declarações dos parâmetros de função extern "C" também correspondem. Você não pode sobrecarregar uma função declarada como extern "C". A partir do Visual Studio 2019 versão 16.3, você pode substituir essa verificação usando a opção /Zc:externC- do compilador após a opção /permissive-.

Confira também

Palavras-chave
Unidades de tradução e ligação
extern Especificador de classe de armazenamento em C
Comportamento de identificadores em C
Vinculação em C