Archivo de cabeceraSe denomina header file, en español fichero/archivo (de) cabecera, o include file, en español fichero de inclusión, en ciencias de computación, especialmente en el ámbito de los lenguajes de programación C y C++, al archivo, normalmente en forma de código fuente, que el compilador incluye de forma automática al procesar algún otro archivo fuente. Típicamente los programadores especifican la inclusión de los header files por medio de pragmas al comienzo (head o cabecera) de otro archivo fuente. Un header file contiene, normalmente, una declaración directa de clases, subrutinas, variables u otros identificadores. Aquellos programadores que desean declarar identificadores estándares en más de un archivo fuente pueden colocar esos identificadores en un único header file, que se incluirá cuando el código que contiene sea requerido por otros archivos. La biblioteca estándar de C y la biblioteca estándar de C++ tradicionalmente declaran sus funciones estándar en header files. MotivaciónEn la mayoría de lenguajes de programación modernos, los programadores pueden dividir los programas en componentes de menor tamaño (como pueden ser clases y subrutinas) y distribuir esos componentes entre muchas unidades por traducir (típicamente en forma de archivos), que el sistema puede compilar de forma autónoma. Si una subrutina se tiene que usar al margen de la unidad por traducir donde ha sido definida, se tiene que introducir el concepto de declaración directa o prototipos de funciones. Por ejemplo, una función definida así en un archivo fuente: int add(int a, int b)
{
return a + b;
}
puede declararse (con un prototipo de función) y ser referida desde un segundo archivo fuente como sigue: int add(int, int);
int triple(int x)
{
return add(x, add(x, x));
}
Sin embargo en esta simple ilustración se requiere que el programador mantenga la declaración de la función de Para entender una violación ODR, considérese el siguiente código (correcto): /* File print-heading.c */
#include <stdio.h>
void print_heading(void)
{
printf("standard heading\n");
}
/* File main.c */
void print_heading(void);
int main(void)
{
print_heading();
return 0;
}
La unidad por traducir representada por el archivo fuente Posteriormente, el programador que mantiene el archivo fuente /* File print-heading.c */
#include <stdio.h>
void print_heading(const char *heading)
{
printf("%s\n", heading);
}
Si el programador olvida actualizar la declaración en ¿Por qué se puede compilar y enlazar este código sin problema alguno? El motivo es que el compilador se guía por la declaración en ¿Cómo es entonces posible llevar a cabo declaraciones múltiples sin problema alguno? La solución se llama header file. El header file de un módulo declara cada función, objeto y tipo de dato que forma parte de la interfaz pública del módulo — por ejemplo, en este caso el header file incluiría solo la delcaración de /* File add.h */
#ifndef ADD_H
#define ADD_H
int add(int, int);
#endif /* ADD_H */
(Nótese que el header file utiliza un "Include guard".) /* File triple.c */
#include "add.h"
int triple(int x)
{
return add(x, add(x, x));
}
Esto reduce la carga del mantenimiento: cuando una definición cambia, solo se tiene que actualizar una única copia de la declaración (la del fichero de cabecera). El fichero de cabecera también se puede incluir en el fichero fuente que contiene las correspondientes definiciones, dándole al compilador la oportunidad de comprobar si la declaración y la definición son consistentes. /* File add.c */
#include "add.h"
int add(int a, int b)
{
return a + b;
}
Normalmente, los programadores solo utilizan los header files para especificar las interfaces, y suelen aportar al menos, una pequeña cantidad de información explicando cómo usar los componentes declarados en el archivo. Al igual que en este ejemplo, las implementaciones de subrutinas permanecen en un archivo fuente separado, que continúa siendo compilado de forma independiente. (Una excepción común entre C y C++ son las "funciones inline", que suelen incluirse en header files porque la mayoría de implementaciones no pueden expendir funciones inline de forma adecuada sin ver sus definiciones durante el tiempo de compilación.) AlternativasLos header files no son la única solución al problema de acceder identificadores declarados en diferentes archivos. Tienen la desventaja de que los programadores siguen teniendo que realizar cambios en dos sitios diferentes (en el archivo fuente y en el header file) cuando se realiza un cambio en una definición. Algunos lenguajes más jóvenes (como Java) prescinden de los header files y usan, en su lugar, un esquema de nombres que permite al compilador localizar los archivos fuente asociados con implementaciones de clases e interfaces (pero, al hacerlo, se restringe la libertad a la hora de nombrar archivos). En estos lenguajes, el problema de ODR se suele resolver por medio de dos técnicas: la primera, el compilador pone toda la información necesaria sobre los tipos en el código compilado y esta información es accesible incluso cuando el programa se ejecuta; la segunda, Java y otros lenguajes modernos tienen la posibilidad de verificar el número y tipo de los argumentos como método de invocación. Todo esto tiene su precio: un exceso en espacio y tiempo de ejecución que no es aceptable para algunas aplicaciones donde el tiempo de respuesta es crítico. COBOL y RPG IV tienen una forma de incluir archivos llamada copybooks. Los programadores "incluyen" estos en la fuente del programa de forma similar a como se hace con los header files, permitiendo también reemplazar ciertas partes del texto. La palabra clave de COBOL para la inclusión es Véase tambiénEnlaces externos
|