¿Cuál de las siguientes declaraciones y definiciones se deben colocar en un archivo de encabezado?
extern int ival = 10; // Inicializador, por lo tanto definición
double fica_rate; // no extern, por lo tanto. es una definición
Aunque ival se declara como externo, tiene un inicializador, lo que significa que la declaración es una definición. Asimismo, la declaración de fica_rate también es una definición, aunque no esté inicializada, ya que no tiene la palabra clave extern. Si dos o más archivos contienen cualquiera de estas definiciones en el mismo programa, se producirá un error de vinculación de definiciones múltiples.
Debido a que los archivos de encabezado se incluyen en varios archivos fuente, no deben contener definiciones de variables o funciones.
Hay tres excepciones a la regla de que los archivos de encabezado no deben contener definiciones. Los archivos de encabezado pueden definir clases, objetos constantes cuyos valores se conocen en el momento de la compilación y funciones en línea. Estas entidades se pueden definir en varios archivos fuente, siempre que la definición sea la misma en cada archivo fuente.
La razón para definir estas entidades en archivos de encabezado es que el compilador necesita sus definiciones (no solo declaraciones) para generar código. Por ejemplo, para generar código que pueda definir o utilizar un objeto de clase, el compilador necesita conocer los miembros de datos que componen el tipo. El compilador también necesita conocer las operaciones que se pueden realizar en estos objetos. La definición de clase proporciona la información requerida. La definición de objetos constantes en archivos de encabezado requiere más explicación.
2. Algunos objetos constantes se definen en archivos de encabezado
Recuerde que las variables constantes son, por defecto, variables locales del archivo en el que están definidas. Como podemos ver ahora, el motivo de esta configuración predeterminada es permitir que se definan variables constantes en los archivos de encabezado.
En C, hay lugares donde se deben colocar expresiones constantes. Por ejemplo, la fórmula de inicialización de un miembro de enumeración debe ser una expresión constante. En capítulos posteriores veremos otros ejemplos en los que se necesitan expresiones constantes.
En términos generales, una expresión constante es una expresión que el compilador puede evaluar en el momento de la compilación. Una variable entera constante puede ser una expresión constante cuando se autoinicializa mediante una expresión constante. Para que una variable constante se convierta en una expresión constante, su inicializador debe ser visible para el compilador. Para que varios archivos utilicen el mismo valor constante, cada archivo debe ver la variable constante y su inicializador. Para que el inicializador sea visible, dicha variable constante generalmente se define en un archivo de encabezado. De esta manera, el compilador puede ver la inicialización cuando se usa la variable constante.
Sin embargo, cualquier variable en C sólo se puede definir una vez. La definición asigna almacenamiento y todos los usos de la variable están asociados con el mismo almacenamiento. Dado que un objeto constante es local por defecto en su archivo de definición, es legal colocar su definición en un archivo de encabezado.
Este comportamiento tiene una implicación importante: cuando definimos una variable constante en un archivo de encabezado, cada archivo fuente que contenga el archivo de encabezado tendrá su propia variable constante con el mismo nombre y valor.
Cuando la variable constante se inicializa usando una expresión constante, se garantiza que todas las variables tendrán el mismo valor. Pero en la práctica, la mayoría de los compiladores reemplazarán cualquier uso de estas variables constantes con expresiones constantes apropiadas en el momento de la compilación. Por lo tanto, en la práctica, una variable constante inicializada con una expresión constante no tendrá espacio de almacenamiento.
Si una variable constante no se inicializa usando una expresión constante, no debe definirse en el archivo de encabezado. En cambio, al igual que otras variables, las variables constantes deben definirse e inicializarse en el archivo fuente. Se debe agregar una declaración externa en el archivo de encabezado para que se pueda acceder a varios archivos.