Respostas:
Quando você escreve um arquivo de implementação ( .cpp
, .cxx
, etc) o seu compilador gera uma unidade de tradução . Este é o arquivo de origem da sua implementação, além de todos os cabeçalhos que você possui #include
.
A ligação interna refere-se a tudo apenas no escopo de uma unidade de tradução .
Ligação externa refere-se a coisas que existem além de uma unidade de tradução específica. Em outras palavras, acessível por todo o programa , que é a combinação de todas as unidades de tradução (ou arquivos de objeto).
const
variáveis (assim como sua finalidade) é totalmente esquecida aqui.
Como dudewat disse que a ligação externa significa que o símbolo (função ou variável global) está acessível em todo o programa e a conexão interna significa que ele está acessível apenas em uma unidade de tradução .
Você pode controlar explicitamente a ligação de um símbolo usando as palavras extern
- static
chave e . Se a ligação não for especificada, a ligação padrão é extern
para não- const
símbolos e static
(interna) para const
símbolos.
// in namespace or global scope
int i; // extern by default
const int ci; // static by default
extern const int eci; // explicitly extern
static int si; // explicitly static
// the same goes for functions (but there are no const functions)
int foo(); // extern by default
static int bar(); // explicitly static
Observe que, em vez de usar static
para ligação interna, é melhor usar namespaces anônimos nos quais você também pode colocar class
es. A ligação para namespaces anônimos mudou entre C ++ 98 e C ++ 11, mas o principal é que eles são inacessíveis a partir de outras unidades de tradução.
namespace {
int i; // external linkage but unreachable from other translation units.
class invisible_to_others { };
}
extern
declaração correspondente no outro arquivo.static
. Diz-se que essas variáveis têm ligação interna .Considere o seguinte exemplo:
void f(int i);
extern const int max = 10;
int n = 0;
int main()
{
int a;
//...
f(a);
//...
f(a);
//...
}
f
declara f
como uma função com ligação externa (padrão). Sua definição deve ser fornecida posteriormente neste arquivo ou em outra unidade de tradução (fornecida abaixo).max
é definido como uma constante inteira. A ligação padrão para constantes é interna . Sua ligação é alterada para externo com a palavra-chave extern
. Então agora max
pode ser acessado em outros arquivos.n
é definido como uma variável inteira. A ligação padrão para variáveis definidas fora dos corpos das funções é externa .#include <iostream>
using namespace std;
extern const int max;
extern int n;
static float z = 0.0;
void f(int i)
{
static int nCall = 0;
int a;
//...
nCall++;
n++;
//...
a = max * z;
//...
cout << "f() called " << nCall << " times." << endl;
}
max
é declarado como tendo ligação externa . Uma definição correspondente para max
(com ligação externa) deve aparecer em algum arquivo. (Como em 1.cpp)n
é declarado como tendo ligação externa .z
é definido como uma variável global com ligação interna .nCall
especifica nCall
ser uma variável que retém seu valor entre as chamadas à função f()
. Diferentemente das variáveis locais com a classe de armazenamento automático padrão, nCall
serão inicializadas apenas uma vez no início do programa e não uma vez para cada chamada de f()
. O especificador de classe de armazenamento static
afeta o tempo de vida da variável local e não seu escopo.NB: A palavra-chave static
desempenha um papel duplo. Quando usado nas definições de variáveis globais, especifica a ligação interna . Quando usado nas definições das variáveis locais, especifica que o tempo de vida da variável será a duração do programa, em vez de ser a duração da função.
Espero que ajude!
static
permite uma inicialização lenta e lenta (o que pode ser útil se você precisar de um objeto global, mas precisar controlar quando ele é construído devido a problemas com a ordem de construção global e não pode alocá-lo dinamicamente) o uso de new
esquemas de inicialização mais detalhados pode estar além do necessário para o objeto em questão; por implicação, isso é principalmente um problema em sistemas incorporados que usam C ++).
Vamos falar sobre escopo diferente em 'C'
ESCOPO: É basicamente quanto tempo posso ver alguma coisa e até que ponto.
Variável local: o escopo está apenas dentro de uma função. Ele reside na área PILHA da RAM. O que significa que toda vez que uma função é chamada, todas as variáveis que fazem parte dessa função, incluindo argumentos de função, são criados recentemente e são destruídos quando o controle sai da função. (Como a pilha é liberada toda vez que a função retorna)
Variável estática: o escopo é para um arquivo. É acessível em qualquer lugar do arquivo
em que é declarado. Ele reside no segmento de dados da RAM. Como isso só pode ser acessado dentro de um arquivo e, portanto, ligação interna. Quaisquer
outros arquivos não podem ver esta variável. De fato, a palavra-chave STATIC é a única maneira pela qual podemos introduzir algum nível de dados ou função
ocultos em 'C'
Variável global: o escopo é para um aplicativo inteiro. É um formulário acessível em qualquer lugar do aplicativo. Variáveis globais também residem no segmento DATA, pois podem ser acessadas em todos os lugares do aplicativo e, portanto, EXTERNAL Linkage
Por padrão, todas as funções são globais. Caso precise ocultar algumas funções de um arquivo de fora, você pode prefixar a palavra-chave estática na função. :-)
Antes de falar sobre a questão, é melhor conhecer o termo unidade de tradução , programa e alguns conceitos básicos de C ++ (na verdade, linkage é um deles em geral) com precisão. Você também precisará saber o que é um escopo .
Vou enfatizar alguns pontos-chave, esp. aqueles que faltam nas respostas anteriores.
Linkage é uma propriedade de um nome , que é introduzida por uma declaração . Nomes diferentes podem denotar a mesma entidade (normalmente, um objeto ou uma função). Portanto, falar sobre vinculação de uma entidade geralmente não faz sentido, a menos que você tenha certeza de que a entidade será referida apenas pelo nome exclusivo de algumas declarações específicas (geralmente uma declaração).
Observe que um objeto é uma entidade, mas uma variável não é. Ao falar sobre o vínculo de uma variável, na verdade o nome da entidade denotada (que é introduzida por uma declaração específica) está em causa. O vínculo do nome está em um dos três: nenhum vínculo, vínculo interno ou vínculo externo.
Unidades de tradução diferentes podem compartilhar a mesma declaração por inclusão no cabeçalho / arquivo de origem (sim, é o texto da norma). Portanto, você pode consultar o mesmo nome em diferentes unidades de tradução. Se o nome declarado tiver ligação externa, a identidade da entidade referida pelo nome também será compartilhada. Se o nome declarado tiver ligação interna, o mesmo nome em diferentes unidades de conversão denota entidades diferentes, mas você pode consultá-la em escopos diferentes da mesma unidade de conversão. Se o nome não tiver vínculo, você simplesmente não poderá consultar a entidade de outros escopos.
(Opa ... Eu achei que o que eu digitei estava apenas repetindo o texto padrão ...)
Existem também outros pontos confusos que não são cobertos pela especificação da linguagem.
__attribute__
ou__declspec
) ou opções do compilador, e a imagem não é o programa inteiro ou o arquivo de objeto traduzido de uma unidade de tradução; portanto, nenhum conceito padrão pode descrevê-lo com precisão. Como símbolo não é um termo normativo em C ++, é apenas um detalhe de implementação, mesmo que as extensões relacionadas de dialetos possam ter sido amplamente adotadas.A regra de ligação da const
variável de escopo do espaço para nome é algo especial (e particularmente diferente do const
objeto declarado no escopo do arquivo na linguagem C, que também possui o conceito de ligação de identificadores). Como o ODR é imposto pelo C ++, é importante manter não mais de uma definição da mesma variável ou função ocorrida em todo o programa, exceto as inline
funções . Se não houver essa regra especial const
, uma declaração mais simples de const
variável com inicializadores (por exemplo = xxx
) em um cabeçalho ou arquivo de origem (geralmente um "arquivo de cabeçalho") incluído por várias unidades de tradução (ou incluídas por uma unidade de tradução mais de uma vez, embora raramente) em um programa viole o ODR, o que faz com queconst
variável como substituição de algumas macros do tipo objeto.
Eu acho que a ligação interna e externa em C ++ fornece uma explicação clara e concisa:
Uma unidade de conversão refere-se a um arquivo de implementação (.c / .cpp) e a todos os arquivos de cabeçalho (.h / .hpp) que ele inclui. Se um objeto ou função dentro de uma unidade de conversão tiver ligação interna, esse símbolo específico será visível apenas para o vinculador dentro dessa unidade de conversão. Se um objeto ou função tiver ligação externa, o vinculador também poderá vê-lo ao processar outras unidades de conversão. A palavra-chave estática, quando usada no espaço para nome global, força um símbolo a ter ligação interna. A palavra-chave extern resulta em um símbolo com ligação externa.
O compilador padroniza a ligação de símbolos, de modo que:
Variáveis globais não const têm ligação externa por padrão
Variáveis globais const têm conexão interna por padrão
Funções têm ligação externa por padrão
A ligação determina se os identificadores com nomes idênticos se referem ao mesmo objeto, função ou outra entidade, mesmo que esses identificadores apareçam em unidades de conversão diferentes. A ligação de um identificador depende de como foi declarado. Existem três tipos de ligações:
Apenas C ++ : você também pode ter vínculo entre fragmentos de código C ++ e não C ++, que é chamado de vínculo de idioma .
Fonte: IBM Program Linkage
Basicamente
extern linkage
variável é visível em todos os arquivosinternal linkage
A variável é visível em um único arquivo.Explicar: variáveis const vinculadas internamente por padrão, a menos que declaradas de outra forma como externas
external linkage
const
variável global éinternal linkage
extern const
variável global extra éexternal linkage
Um material muito bom sobre ligação em C ++
http://www.goldsborough.me/c/c++/linker/2016/03/30/19-34-25-internal_and_external_linkage_in_c++/
Em C ++
Qualquer variável no escopo do arquivo e que não esteja aninhada dentro de uma classe ou função, é visível em todas as unidades de tradução em um programa. Isso é chamado de ligação externa porque, no momento do link, o nome fica visível para o vinculador em qualquer lugar, externo a essa unidade de tradução.
Variáveis globais e funções comuns têm ligação externa.
O objeto estático ou o nome da função no escopo do arquivo é local para a unidade de conversão. Isso é chamado de ligação interna
Vinculação refere-se apenas a elementos que possuem endereços no momento do link / carregamento; portanto, declarações de classe e variáveis locais não têm ligação.