C++ extern palabra clave en funciones. ¿Por qué no solo incluir el archivo de cabecera?


Si lo entiendo correctamente esto significa

extern void foo();

Que la función foo se declara en otra unidad de traducción.

1) ¿Por qué no solo #incluir el encabezado en el que se declara esta función?

2) ¿Cómo sabe el enlazador dónde buscar la función en el tiempo de enlace?

Editar: Tal vez debería aclarar que la declaración anterior es seguida por el uso de la función

foo();

Nunca se define en esta unidad de traducción.

Author: user199421, 2010-04-09

5 answers

1) Puede no tener un archivo de cabecera. Pero sí, en general, para proyectos grandes, debe tener un archivo de encabezado si varias unidades de traducción van a usar esa función (no se repita).

2) El enlazador busca a través de todos los archivos objeto y bibliotecas de las que se le informó para encontrar funciones y otros símbolos.

 26
Author: Brian Neal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-08 23:52:34

No, esto significa que la función foo se declara con vinculación externa. Enlace externo significa que name foo se refiere a la misma función en todo el programa. Donde se define la función no importa. Se puede definir en esta unidad de traducción. Se puede definir en otra unidad de traducción.

Usar la palabra clave extern como se muestra en su ejemplo es superfluo. Las funciones siempre tienen enlace externo por defecto. Lo anterior es 100% equivalente a solo

void foo();

En cuanto a el enlazador, cuando el enlazador enlaza el programa, simplemente se ve en todas partes . Revisa todas las definiciones hasta encontrar la definición de foo.

 15
Author: AnT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-09 00:07:29

Como otros ya han dicho, la palabra clave extern se usa para indicar que el nombre (una variable o función) tiene enlace externo, lo que significa que el nombre se refiere al mismo objeto en todo el programa. Además, este es el valor predeterminado para las variables y funciones definidas en el ámbito del archivo, por lo que este uso es superfluo.

Hay otro uso de la palabra clave extern que va así:

extern "C" void foo();

Esto significa que la función foo se vinculará usando las convenciones C para el enlace (tal vez porque esto es una función definida en una biblioteca de C o es una función destinada a ser llamada por programas de C).

 14
Author: goedson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-06 16:43:15

Ya significa que sin la palabra clave extern. Las funciones tienen enlace externo por defecto, a menos que las declare estáticas.

Usar prototipos de funciones está bien, pero es fácil equivocarse. El error del enlazador que obtendrá no es tan fácil de diagnosticar cuando redefine la implementación de la función. El enlazador no sabe dónde buscar, es su trabajo darle un archivo de objeto que contenga la definición de la función para mantenerlo feliz.

 8
Author: Hans Passant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-09 00:01:08

1) No se por qué necesitaría esto para una función. Tal vez alguien más pueda intervenir.

2) El enlazador determina esto revisando todos los archivos objeto y comprobando los símbolos dentro de cada archivo objeto. Supongo que dependiendo de su enlazador, el orden exacto de búsqueda puede variar.

Para GNU binutils ' ld todos los archivos objeto y bibliotecas que aparecen en la línea de comandos del enlazador después del objeto que contiene el símbolo que falta se buscan de izquierda a derecha y el primer símbolo encontrado es elegido.

Ejemplo 1:

  • a. o uses usa foo (), bar ()
  • liba provides proporciona bar ()
  • libb provides proporciona foo ()

> > ld a. o-la-lb

Hará que a.o sea buscado por símbolos indefinidos. A partir de entonces ld irá a través de las libs de izquierda a derecha para buscar estos símbolos y encontrará bar en liba y foo en libb.

Esto puede llevar a problemas extraños en dependencias circulares:

Ejemplo 2:

  • a. o uses usa bar ()
  • liba provides proporciona bar(), usa foo()
  • libb provides proporciona foo (), usa bar ()

Ahora, hay una dependencia circular entre liba y libb y el enlace fallará:

> > ld a. o-la-lb

Porque al buscar a través de los símbolos indefinidos en libb, ld determinará que no hay otro lib a la derecha de-lb que proporcione este símbolo. Esto se puede arreglar de al menos dos maneras:

1) enlace liba dos veces: $> ld a. o-la-lb-la

2) utilice la función de agrupación de ld start > ld a.o start start-group-la-lb {end-group

En el caso 2), la agrupación le dice a ld que busque entre todos los símbolos en todas las libs que pertenecen a este grupo.

 2
Author: BjoernD,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-09 00:04:50