extern

extern es una palabra clave que se usa en el lenguaje de programación C para marcar que un símbolo, como una función o una variable global, es externo, es decir, no está declarado en un archivo .c pero sí está en otra parte. Con esto dejamos que la etapa de compilación salga adelante, indicando los tipos de ese símbolo externo, pero sin que el compilador reserve memoria para esa variable. El enlazador tendrá que cerrar las referencias. extern se usa más en variables globales, porque en funciones no es necesario ya que implícitamente se asume que un prototipo de función es externo. Algunos compiladores modernos nos permiten omitir el extern y saben cuando una variable es tentativa, pero como os enseño en este vídeo, crea mucha ambigüedad, motivo por el cual es deseable usar extern siempre que se trabaje con símbolos externos.

La palabra clave extern en C es fundamental para trabajar con variables globales y funciones que están definidas en archivos diferentes al que estamos compilando. Cuando repartimos nuestro programa en varios archivos fuente, como main.c y funciones.c, el compilador necesita saber que ciertas funciones o variables existen en otros archivos para poder compilar correctamente cada unidad de compilación por separado.

En el caso de las funciones, normalmente basta con declarar sus prototipos en el archivo donde las usamos. Por ejemplo, si tenemos funciones como incrementar_contador e imprimir_contador definidas en funciones.c, en main.c solo necesitamos declarar sus prototipos:

void incrementar_contador(void);
void imprimir_contador(void);

Con esto, el compilador entiende que esas funciones existen en otra parte y deja que el enlazador se encargue de unirlas. En este contexto, usar extern explícitamente en los prototipos de funciones no es necesario, ya que el compilador asume implícitamente que son externas.

Sin embargo, cuando hablamos de variables globales, la situación cambia. Si tenemos una variable global, por ejemplo contador, definida en un archivo contador.c así:

unsigned int contador = 1;

y queremos usarla en otro archivo, como en funciones.c, debemos indicarle al compilador que esa variable existe en otro lugar. Para ello, usamos la palabra clave extern en la declaración:

extern unsigned int contador;

Esto le dice al compilador que contador no es una variable nueva en este archivo, sino que está definida externamente. Sin esta declaración, el compilador no sabe qué tipo tiene contador y puede generar errores o, en algunos compiladores, crear una variable global tentativa que puede causar conflictos al enlazar.

El comportamiento exacto puede variar según el compilador. Algunos, como Clang (parte de LLVM), permiten que si no usamos extern en la declaración de la variable global, se cree una variable tentativa que se resolverá en tiempo de enlace si existe una definición con valor inicial en otro archivo. Esto puede hacer que el programa compile y funcione aunque no hayamos puesto extern. Por ejemplo, si en funciones.c declaramos:

unsigned int contador;

sin inicializarla, y en contador.c la definimos con un valor inicial, el enlazador usará la definición con valor inicial y todo funcionará bien.

Pero otros compiladores, como ciertas versiones de GCC en Linux, no permiten esta ambigüedad y exigen que usemos extern para declarar variables globales definidas en otros archivos. Si no lo hacemos, el enlazador detectará múltiples definiciones de la misma variable y fallará.

Por lo tanto, para evitar problemas y asegurar portabilidad, es recomendable siempre declarar las variables globales externas con extern en los archivos donde las usamos, y definirlas sin extern en un único archivo donde se inicializan.

En resumen, extern es la forma que tiene C para indicarle al compilador que una variable global o función está definida en otro archivo, permitiendo que el compilador y enlazador gestionen correctamente las referencias cruzadas entre múltiples archivos fuente. Mientras que para funciones basta con sus prototipos, para variables globales es esencial usar extern para evitar conflictos y errores de compilación.

Lista de reproducción
  1. 1
    Instalar CodeBlocks
    15 minutos
  2. 2
    Funciones y hola mundo
    17 minutos
  3. 3
    Variables y tipos de datos
    17 minutos
  4. 4
    Condicionales y operadores lógicos
    16 minutos
  5. 5
    Bucles
    11 minutos
  6. 6
    Punteros
    12 minutos
  7. 7
    Arrays
    14 minutos
  8. 8
    Estructuras
    12 minutos
  9. 9
    Otras construcciones de C
    9 minutos
  10. 10
    Memoria dinámica
    8 minutos
  11. 11
    El preprocesador (parte 1)
    10 minutos
  12. 12
    El preprocesador (parte 2)
    9 minutos
  13. 13
    Archivos de cabecera y múltiples .c (parte 1)
    8 minutos
  14. 14
    Archivos de cabecera y múltiples .c (parte 2)
    9 minutos
  15. 15
    C desde la línea de comandos (parte 1)
    8 minutos
  16. 16
    C desde la línea de comandos (parte 2)
    9 minutos
  17. 17
    Break y continue
    10 minutos
  18. 18
    Goto
    13 minutos
  19. 19
    Manipulación de bits
    15 minutos
  20. 20
    Máscaras de bit
    19 minutos
  21. 21
    Archivos (1): fopen y fclose
    13 minutos
  22. 22
    Archivos (2): leer con fgetc
    9 minutos
  23. 23
    Archivos (3): fseek y ftell
    11 minutos
  24. 24
    Archivos (4): leer con fgets
    9 minutos
  25. 25
    Archivos (5): fputc y fputs
    7 minutos
  26. 26
    Archivos (6): volcar en archivos con fwrite
    10 minutos
  27. 27
    Archivos (7): fread, fwrite y los arrays
    10 minutos
  28. 28
    Archivos (8): entrada estándar y salida estándar
    9 minutos
  29. 29
    Archivos (9): buffers
    14 minutos
  30. 30
    Archivos (y 10): otras funciones útiles con archivos
    5 minutos
  31. 31
    printf (1)
    18 minutos
  32. 32
    printf (parte 2)
    12 minutos
  33. 33
    scanf (parte 1)
    17 minutos
  34. 34
    scanf (parte 2)
    17 minutos
  35. 35
    fprintf, sprintf y snprintf
    8 minutos
  36. 36
    Tipos de datos opacos
    13 minutos
  37. 37
    Bibliotecas estáticas
    13 minutos
  38. 38
    Bibliotecas dinámicas
    15 minutos
  39. 39
    Más flags: i mayúscula (include), wall, werror, pedantic...
    12 minutos
  40. 40
    pkg-config
    12 minutos
  41. 41
    Make
    17 minutos
  42. 42
    GDB
    21 minutos
  43. 43
    Variables globales
    6 minutos
  44. 44
    extern
    9 minutos
  45. 45
    Funciones variádicas
    12 minutos
  46. 46
    El optimizador de GCC y la opción -O
    12 minutos
  47. 47
    Volatile
    6 minutos