
lilq
Mi pregunta es sobre cuándo se debe hacer referencia a una función con el extern
palabra clave en C.
No veo cuándo debería usarse esto en la práctica. Mientras escribo un programa, todas las funciones que uso están disponibles a través de los archivos de encabezado que he incluido. Entonces, ¿por qué sería útil extern
para obtener acceso a algo que no estaba expuesto en el archivo de encabezado?
Podría estar pensando en cómo extern
funciona incorrectamente, y si es así por favor corrígeme.
También… ¿Deberías extern
algo cuando es la declaración predeterminada sin la palabra clave en un archivo de encabezado?

hermano azul
extern
cambia el enlace. Con la palabra clave, se supone que la función/variable está disponible en otro lugar y la resolución se delega al enlazador.
Hay una diferencia entre extern
sobre funciones y sobre variables.
Para Variables no instancia la variable en sí, es decir, no asigna ninguna memoria. Esto debe hacerse en otro lugar. Por lo tanto, es importante si desea importar la variable desde otro lugar.
Para funciones, esto solo le dice al compilador que el enlace es externo. Como este es el valor predeterminado (se utiliza la palabra clave static
para indicar que una función no está vinculada mediante un enlace externo), no necesita usarla explícitamente.

lilq
extern
le dice al compilador que estos datos están definidos en algún lugar y se conectarán con el enlazador.
Con la ayuda de las respuestas aquí y hablando con algunos amigos aquí está el ejemplo práctico de un uso de extern
.
Ejemplo 1 – para mostrar una trampa:
stdio.h
:
int errno;
myCFile1.c
:
#include <stdio.h>
// Code using errno...
myCFile2.c
:
#include <stdio.h>
// Code using errno...
Si myCFile1.o
y myCFile2.o
están vinculados, cada uno de los archivos c tiene copias separadas de errno
. Este es un problema como el mismo errno
se supone que está disponible en todos los archivos vinculados.
Ejemplo 2 – La solución.
stdio.h
:
extern int errno;
stdio.c
:
int errno;
myCFile1.c
:
#include <stdio.h>
// Code using errno...
myCFile2.c
:
#include <stdio.h>
// Code using errno...
ahora si los dos myCFile1.o
y MyCFile2.o
están vinculados por el enlazador, ambos apuntarán al mismo errno
. Así, resolviendo la implementación con extern
.

aib
Ya se ha dicho que la extern
la palabra clave es redundante para las funciones.
En cuanto a las variables compartidas entre las unidades de compilación, debe declararlas en un archivo de encabezado con la palabra clave extern y luego definirlas en un solo archivo fuente, sin la palabra clave extern. El único archivo de origen debe ser el que comparte el nombre del archivo de encabezado, como práctica recomendada.

Christian Gingras
Muchos años después, descubro esta pregunta. Después de leer cada respuesta y comentario, pensé que podría aclarar algunos detalles… Esto podría ser útil para las personas que llegan aquí a través de la búsqueda de Google.
La pregunta es específicamente sobre el uso extern
funciones, por lo que voy a ignorar el uso de extern
con variables globales.
Definamos 3 prototipos de funciones:
// --------------------------------------
// Filename: "my_project.H"
extern int function_1(void);
static int function_2(void);
int function_3(void);
El archivo de encabezado puede ser utilizado por el código fuente principal de la siguiente manera:
// --------------------------------------
// Filename: "my_project.C"
#include "my_project.H"
void main(void) {
int v1 = function_1();
int v2 = function_2();
int v3 = function_3();
}
int function_2(void) return 1234;
Para compilar y vincular, debemos definir function_2
en el mismo archivo de código fuente donde llamamos a esa función. Las otras dos funciones podrían definirse en un código fuente diferente *.C
o pueden estar ubicados en cualquier archivo binario (*.OBJ
, *.LIB
, *.DLL
), por lo que es posible que no tengamos el código fuente.
Incluyamos de nuevo el encabezado. my_project.H
en un diferente *.C
archivo para entender mejor la diferencia. En el mismo proyecto, añadimos el siguiente archivo:
// --------------------------------------
// Filename: "my_big_project_splitted.C"
#include "my_project.H"
void old_main_test(void){
int v1 = function_1();
int v2 = function_2();
int v3 = function_3();
}
int function_2(void) return 5678;
int function_1(void) return 12;
int function_3(void) return 34;
Características importantes a tener en cuenta:
-
Cuando una función se define como static
en un archivo de encabezado, el compilador/enlazador debe encontrar una instancia de una función con ese nombre en cada módulo que usa ese archivo de inclusión.
-
Una función que es parte de la biblioteca C puede ser reemplazada en un solo módulo redefiniendo un prototipo con static
solo en ese modulo. Por ejemplo, reemplace cualquier llamada a malloc
y free
para agregar la función de detección de fugas de memoria.
-
el especificador extern
no es realmente necesario para las funciones. Cuando static
no se encuentra, siempre se supone que una función es extern
.
-
Sin embargo, extern
no es el valor predeterminado para las variables. Normalmente, cualquier archivo de encabezado que defina variables para que sean visibles en muchos módulos debe usar extern
. La única excepción sería si se garantiza la inclusión de un archivo de encabezado de un único módulo.
Muchos gerentes de proyecto requerirían que dicha variable se coloque al comienzo del módulo, no dentro de ningún archivo de encabezado. Algunos proyectos grandes, como el emulador de videojuegos “Mame”, incluso requieren que tales variables aparezcan solo sobre la primera función que las usa.

Steve Melnikoff
Cª, extern
está implícito para los prototipos de funciones, ya que un prototipo declara una función que se define en otro lugar. En otras palabras, un prototipo de función tiene un enlace externo por defecto; utilizando extern
está bien, pero es redundante.
(Si se requiere un enlace estático, la función debe declararse como static
tanto en su prototipo como en el encabezado de la función, y normalmente ambos deberían estar en el mismo archivo .c).

qris
Un muy buen articulo que me llego sobre el extern
palabra clave, junto con los ejemplos: http://www.geeksforgeeks.org/understanding-extern-keyword-in-c/
Aunque no estoy de acuerdo en que usar extern
en las declaraciones de funciones es redundante. Se supone que esto es una configuración del compilador. Así que recomiendo usar el extern
en las declaraciones de funciones cuando sea necesario.
Si cada archivo en su programa se compila primero en un archivo de objeto, entonces los archivos de objeto se vinculan entre sí, necesita extern
. Le dice al compilador “Esta función existe, pero el código para ella está en otro lugar. No se asuste”.
relacionado para funciones: stackoverflow.com/questions/856636/… para varables: stackoverflow.com/questions/1433204
– Ciro Santilli Путлер Капут 六四事
19 de junio de 2015 a las 2:16