Cuando escribimos algo como:
#include <iostream>
podría parecer que el compilador “importa” la librería, pero en realidad el #include no es parte del lenguaje, sino una instrucción del preprocesador.
Lo que hace es copiar literalmente el contenido del archivo incluido dentro del código antes de compilar.
Por ejemplo, si tenés:
#include "miarchivo.h"
el preprocesador reemplaza esa línea por el texto completo de miarchivo.h.
Así, el compilador ve un solo archivo unificado.
¿Y qué pasa con las librerías estándar? Cuando hacés #include <iostream>, el compilador busca ese archivo en los directorios del sistema (por ejemplo, /usr/include/c++/ en Linux).
Ese archivo sí existe y contiene declaraciones, no implementaciones.
Por ejemplo:
namespace std {
extern ostream cout;
}
El archivo de cabecera sólo declara las funciones y objetos que vas a usar. Las implementaciones están en archivos binarios precompilados (.a, .lib, .so, .dll), que se vinculan en la etapa de linking.
El proceso completo es así:
- Preprocesador: copia los headers (#include) y expande macros.
- Compilación: convierte cada .cpp en un archivo objeto.
- Linker: une esos objetos con las librerías que contienen las funciones reales.
Como los headers se copian literalmente, si se incluyen varias veces puede haber redefiniciones.
Por eso se usan las llamadas guardas de inclusión:
#ifndef MIARCHIVO_H
#define MIARCHIVO_H
// contenido
#endif
o la forma moderna:
#pragma once
En resumen, #include no importa código ejecutable:
- solo inserta declaraciones que el compilador necesita conocer.
- El código real vive en las librerías que se enlazan al final del proceso.
