Pergunta

Eu estou tomando linguagens de programação curso e estamos a falar sobre a extern "C" declaração.

Como é que esta declaração de trabalho em um nível mais profundo, diferente de "ele interfaces de C e C++"?Como isso afeta as ligações que ocorrem no programa bem?

Foi útil?

Solução

extern "C" é usado para garantir que os símbolos a seguir não sejam mutilado (decorado).


Exemplo:

Digamos que temos o seguinte código em um arquivo chamado test.cpp:

extern "C" {
  int foo() {
    return 1;
  }
}

int bar() {
  return 1;
}

Se você correr gcc -c test.cpp -o test.o

Dê uma olhada nos nomes dos símbolos:

00000010 T _Z3BARV

00000000 T FOO

foo() Mantém o nome.

Outras dicas

Vejamos uma função típica que pode compilar em C e C ++:

int Add (int a, int b)
{
    return a+b;
}

Agora, em C, a função é chamada de "_add" internamente. Enquanto a função C ++ é chamada de algo completamente diferente usando um sistema chamado nomes de nomes. É basicamente uma maneira de nomear uma função para que a mesma função com parâmetros diferentes tenha um nome interno diferente.

Portanto, se Add () for definido em add.c e você ter o protótipo em add.h, você terá um problema se tentar incluir add.h em um arquivo C ++. Como o código C ++ está procurando uma função com um nome diferente do que add.c, você receberá um erro de vinculador. Para contornar esse problema, você deve incluir add.c por este método:

extern "C"
{
#include "add.h"
}

Agora, o código C ++ será vinculado ao _Add em vez da versão mutilada do nome C ++.

Esse é um dos usos da expressão. Resumindo, se você precisar compilar o código que é estritamente C em um programa C ++ (por meio de uma instrução INCLUÍDO ou ALGUNS MUNDOS), você precisa embrulhá -lo com uma declaração externa "C" {...}.

Quando você sinaliza um bloco de código com "C" externo, você está dizendo ao sistema para usar a ligação do estilo C.

Isso, principalmente, afeta a maneira como o vinculador engana os nomes. Em vez de usar o nome do estilo C ++ (que é mais complexo para suportar sobrecargas do operador), você obtém a nomeação padrão do estilo C do vinculador.

Em C ++, o nome/símbolo das funções é realmente renomeado para outra coisa, de modo que diferentes classes/namespaces podem ter funções das mesmas assinaturas. Em C, as funções são todas definidas globalmente e esse processo de renomeação personalizado é necessário.

Para fazer C ++ e C conversarem entre si, "extern c" instrui o compilador a não usar a Convenção C.

Deve -se notar que extern "C" também modifica os tipos de funções. Ele não apenas modifica as coisas em níveis mais baixos:

extern "C" typedef void (*function_ptr_t)();

void foo();

int main() { function_ptr_t fptr = &foo; } // error!

O tipo de &foo Não é igual ao tipo que o typedef designa (embora o código seja aceito por alguns, mas não todos os compiladores).

extern c afeta o nome do nome do compilador C ++. É uma maneira de fazer com que o compilador C ++ não gerencie nomes, ou melhor, para gerenciá -los da mesma maneira que um compilador C faria. É assim que ele interfina C e C ++.

Como um exemplo:

extern "C" void foo(int i);

permitirá que a função seja implementada em um módulo C, mas permitirá que ela seja chamada de um módulo C ++.

O problema surge ao tentar obter um módulo C para chamar uma função C ++ (obviamente C não pode usar classes C ++) definidas em um módulo C ++. O compilador C não gosta extern "C".

Então você precisa usar isso:

#ifdef __cplusplus
extern "C" {
#endif

void foo(int i);

#ifdef __cplusplus
}
#endif

Agora, quando isso aparecer em um arquivo de cabeçalho, os compiladores C e C ++ ficarão felizes com a declaração e agora poderão ser definidos no módulo C ou C ++ e podem ser chamados pelo código C e C ++.

Externo "C" indica que o código fechado usa vinculação e nome do estilo C. O C ++ usa um formato de mangueira de nome mais complexo. Aqui está um exemplo:

http://en.wikipedia.org/wiki/Name_Mangling

int example(int alpha, char beta);

Em C: _example

em C ++: __Z7exampleic

ATUALIZAÇÃO: Como observa Gmannickg nos comentários, o padrão de manglom de nome é dependente do compilador.

extern "c", é uma palavra -chave para declarar uma função com as ligações C, porque o compilador C e o compilador C ++ traduzirão a fonte em formato diferente no arquivo de objeto:

Por exemplo, um snippet de código é o seguinte:

int _cdecl func1(void) {return 0}
int _stdcall func2(int) {return 0}
int _fastcall func3(void) {return 1}

Os compiladores C de 32 bits traduzirão o código no formulário da seguinte forma:

_func1
_func2@4
@func3@4

No CDECL, Func1 se traduzirá como '_nome'

No stdcall, o func2 se traduzirá como '_name@x'

No FastCall, o Func2 se traduzirá como '@nome@x'

'X'significa quantos bytes dos parâmetros na lista de parâmetros.

Convenção de 64 bits no Windows não tem sublinhado líder

Em C ++, classes, modelos, espaços para nome e sobrecarga do operador são introduzidos, pois não é permitido duas funções com o mesmo nome, o compilador C ++ fornece as informações de tipo no nome do símbolo,

Por exemplo, um snippet de código é o seguinte:

int func(void) {return 1;}
int func(int) {return 0;}
int func_call(void) {int m=func(), n=func(0);}

O compilador C ++ traduzirá o código da seguinte forma:

int func_v(void) {return 1;}
int func_i(int) {return 0;}
int func_call(void) {int m=_func_v(), n=_func_i(0);}

'_v' e '_i' são informações de tipo de 'void' e 'int'

Aqui está uma citação do msdn

"A palavra-chave externo declara uma variável ou função e especifica que ele tem ligação externa a (o seu nome é visível a partir de arquivos diferente daquele no qual ela está definida).Ao modificar uma variável, externo especifica que a variável tem a duração de estática (é alocado quando o programa começa e desalocado quando o programa termina).A variável ou função pode ser definida em outro arquivo de origem, ou mais tarde no mesmo arquivo.Declarações de variáveis e funções no âmbito do ficheiro são externas por padrão."

http://msdn.microsoft.com/en-us/library/0603949d%28VS.80%29.aspx

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top