Pregunta

Estoy tomando un curso de lenguajes de programación y estamos hablando del extern "C" declaración.

¿Cómo funciona esta declaración en un nivel más profundo que no sea "Interfaces C y C ++"? ¿Cómo afecta esto a los enlaces que tienen lugar en el programa también?

¿Fue útil?

Solución

extern "C" se usa para garantizar que los símbolos siguientes no sean maltratado (decorado).


Ejemplo:

Digamos que tenemos el siguiente código en un archivo llamado test.cpp:

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

int bar() {
  return 1;
}

Si tu corres gcc -c test.cpp -o test.o

Eche un vistazo a los nombres de los símbolos:

00000010 T _Z3BARV

0000000000 t foo

foo() mantiene su nombre.

Otros consejos

Veamos una función típica que puede compilar tanto en C como en C ++:

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

Ahora en C, la función se llama "_Add" internamente. Mientras que la función C ++ se llama algo completamente diferente internamente usando un sistema llamado Name-Mangling. Es básicamente una forma de nombrar una función para que la misma función con diferentes parámetros tenga un nombre interno diferente.

Entonces, si add () se define en add.c, y tiene el prototipo en add.h obtendrá un problema si intenta incluir add.h en un archivo c ++. Debido a que el código C ++ está buscando una función con un nombre diferente al de add.c, obtendrá un error de enlazador. Para evitar ese problema, debe incluir add.c mediante este método:

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

Ahora el código C ++ vinculará con _Add en lugar de la versión destrozada por el nombre de C ++.

Ese es uno de los usos de la expresión. En pocas palabras, si necesita compilar un código que es estrictamente C en un programa C ++ (a través de una declaración de inclusión o algún otro medio), debe envolverlo con una declaración externa "C" {...}.

Cuando marca un bloque de código con "C" extern, le está diciendo al sistema que use el enlace de estilo C.

Esto, principalmente, afecta la forma en que el enlazador mangula los nombres. En lugar de usar la gestión de nombre de estilo C ++ (que es más complejo para admitir sobrecargas del operador), obtiene el nombre estándar de estilo C del enlazador.

En C ++, el nombre/símbolo de las funciones en realidad se renombra a otra cosa que diferentes clases/espacios de nombres pueden tener funciones de las mismas firmas. En C, todas las funciones están definidas a nivel mundial y no se necesita tal proceso de cambio de nombre personalizado.

Para hacer que C ++ y C hablen entre sí, "extern C" instruye al compilador que no use la convención C.

se debe notar que extern "C" También modifica los tipos de funciones. No solo modifica las cosas en los niveles inferiores:

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

void foo();

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

El tipo de &foo no es igual al tipo que el typedef designa (aunque el código es aceptado por algunos, pero no todos los compiladores).

ex externo afecta el nombre de la gestión del compilador C ++. Es una forma de hacer que el compilador C ++ no mangle los nombres, o más bien para destrozarlos de la misma manera que lo haría un compilador C. Esta es la forma en que interactúa C y C ++.

Como ejemplo:

extern "C" void foo(int i);

Permitirá que la función se implementará en un módulo C, pero permitirá que se llame desde un módulo C ++.

El problema se produce cuando se intenta obtener un módulo C para llamar a una función C ++ (obviamente C no puede usar clases C ++) definida en un módulo C ++. Al compilador C no le gusta extern "C".

Entonces necesitas usar esto:

#ifdef __cplusplus
extern "C" {
#endif

void foo(int i);

#ifdef __cplusplus
}
#endif

Ahora, cuando esto aparezca en un archivo de encabezado, los compiladores C y C ++ estarán contentos con la declaración y ahora podría definirse en un módulo C o C ++, y puede llamarse por el código C y C ++.

Extern "C" denota que el código adjunto utiliza vinculación de estilo C y mangling de nombre. C ++ utiliza un formato de mangación de nombre más complejo. Aquí hay un ejemplo:

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

int example(int alpha, char beta);

Cía: _example

En C ++: __Z7exampleic

ACTUALIZACIÓN: Como señala Gmannickg en los comentarios, el patrón de nombre en seco depende del compilador.

Extern "C", es una palabra clave para declarar una función con enlaces C, porque el compilador C y el compilador C ++ traducirán la fuente en diferente forma en el archivo de objeto:

Por ejemplo, un fragmento de código es el siguiente:

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

Los compiladores C de 32 bits traducirán el código en el formulario de la siguiente manera:

_func1
_func2@4
@func3@4

En el CDECL, FUNC1 se traducirá como '_nombre'

En el stdcall, Func2 se traducirá como '_name@x'

En FastCall, Func2 se traducirá como '@nombre@x'

'X'significa cuántos bytes de los parámetros en la lista de parámetros.

La convención de 64 bits en Windows no tiene un subrayador líder

En C ++, se introducen clases, plantillas, espacios de nombres y sobrecarga del operador, ya que no se les permite dos funciones con el mismo nombre, el compilador C ++ proporciona la información de tipo en el nombre del símbolo,

Por ejemplo, un fragmento de código es el siguiente:

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

El compilador C ++ traducirá el código de la siguiente manera:

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' y '_i' son información de tipo de 'void' e 'int'

Aquí hay una cita de msdn

"La palabra clave externa declara una variable o función y especifica que tiene un enlace externo (su nombre es visible desde archivos que no sean aquel en el que se define). Al modificar una variable, extern especifica que la variable tiene una duración estática (se asigna Cuando el programa comienza y se desaconseja cuando finaliza el programa). La variable o función puede definirse en otro archivo fuente, o más tarde en el mismo archivo. Declaraciones de variables y funciones en el alcance del archivo son externas de forma predeterminada ".

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top