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 de funciones "externas", por lo que ignoraré el uso de "externas" 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 se pueden definir en un código fuente diferente " .C" o se pueden ubicar en cualquier archivo binario ( .OBJ, * .LIB, * .DLL), para el cual es posible que no tengamos el código fuente.
Incluyamos nuevamente el encabezado "my_project.H" en un archivo "* .C" diferente para comprender mejor la diferencia. En el mismo proyecto, agregamos 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 "estática" en un archivo de encabezado, el compilador / vinculador debe encontrar una instancia de una función con ese nombre en cada módulo que utiliza ese archivo de inclusión.
Una función que forma parte de la biblioteca C puede reemplazarse en un solo módulo redefiniendo un prototipo con "estático" solo en ese módulo. Por ejemplo, reemplace cualquier llamada a "malloc" y "gratis" para agregar la función de detección de pérdida de memoria.
El especificador "extern" no es realmente necesario para las funciones. Cuando no se encuentra "estático", siempre se supone que una función es "externa".
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 que un archivo de encabezado se incluya desde un solo módulo.
Muchos administradores de proyectos 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 dicha variable aparezca solo por encima de la primera función que los usa.