2010-10-28 4 views

Respuesta

8

Hay algunos casos de uso para esto. El más obvio es que su programa principal rara vez necesita un archivo de encabezado.

El segundo es donde no tiene un encabezado para cada archivo C. He reunido bibliotecas antes (digamos una biblioteca BTree a los efectos de esta respuesta), donde cada función individual está en su propio archivo de origen, pero hay un archivo de cabecera de toda la biblioteca, algo así como:

btree.h 
btree_priv.h 
btreeInit.c 
btreeDestroy.c 
btreeConfig.c 

y pronto. El archivo de encabezado privado es para las cosas que deben ser compartidas entre el código, pero no debe publicarse en la API.

+0

Así que supongo que un corolario de esta respuesta es que el patrón de fachada a menudo conducirá a una relación .c to .h no uno a uno. – Tommy

5

más obviamente cuando el .c es completamente autónomo y no necesita tener prototipos o extern para otros archivos .c. esto básicamente es solo para programas muy pequeños, o aquellos que exportan a través de un archivo def para completar una interfaz predefinida.

1

En caso de que no necesite las declaraciones del archivo .h, pero eso nunca es efectivo.

3

Cuando el archivo .c contiene datos que no necesitan ser utilizados por ningún código.

Es cierto que esto es raro, pero puede suceder. Por ejemplo, he hecho esto en dispositivos integrados, para llenar el búfer del cuadro de video con gráficos de arranque.

3

Si divide su programa en una serie de módulos, generalmente habrá un módulo "principal", que contiene la función main() y quizás algunas otras cosas. Si este módulo no tiene nada que deba llamar o usar otro módulo, no necesita exportar una interfaz en un archivo .h.

5

He visto bases de código masivas donde un único archivo .h define la interfaz de algún componente, y varios archivos .c lo implementan. La implementación se dividió en varios archivos por razones de mantenimiento, y se intentó en algunos límites lógicos.

Podría argumentarse que tal límite lógico podría aplicarse para dividir el componente en subcomponentes y, en consecuencia, tener varios archivos de encabezado, pero las decisiones de diseño rara vez son de color blanco &, y en ocasiones este enfoque tiene sentido.

1

A menudo, crearé un archivo de encabezado para 'main' incluso si no espero que otro código tenga que acceder a él, ya que frecuentemente (1) una compilación de depuración terminará requiriendo algo fuera del módulo principal para acceder a algo dentro de él, o (2) el módulo principal terminará teniendo que ser dividido debido a las limitaciones del compilador (sistema incorporado). El patrón de tener cada archivo .c incluye su propio archivo .h es lo suficientemente fuerte como para crear a menudo archivos .h casi vacíos incluso para archivos .c que definen cosas que no están referenciadas en el código (como las tablas de interrupción-salto) , etc.)

Las convenciones de nomenclatura se vuelven un poco más complicadas cuando un archivo incluye varios archivos generados por el programa o incluye archivos que deben compilarse más de una vez (p.uno de mis proyectos tiene dos motores, cuyo código es idéntico, excepto que usan diferentes puertos de E/S y diferentes variables; motor.c mi archivo contiene:

 
#define LOCK L0 
#include "motor.i" 
#undef LOCK 
#define LOCK L1 
#include "motor.i" 
#under LOCK 

Tenga en cuenta que en este compilador incrustado en particular, el operador -> es muy ineficiente, por lo que una afirmación como:

 
    L0.speed++; 

compilará a uno instrucciones, mientras que una declaración como:

 
    L0->speed++; 

se traduce en cinco instrucciones si 'velocidad' es el primer elemento de la estructura, o siete si ocupa cualquier otra posición. Por lo tanto, es mucho más eficiente en velocidad, y algo más eficiente en el uso del espacio, duplicar el código con direcciones de resolución constantes que tener una rutina que maneje ambos motores.

Si hay un archivo adicional asociado con un archivo .c y contiene código real, lo llamaré ".i". Sin embargo, no estoy seguro de qué hacer si hay más de uno.

3

Creo que esperar un mapeo de 1 a 1 entre archivos .c y .h es una suposición de partida incorrecta. Tíralo y comienza de nuevo. : D

Al ver su pregunta de manera diferente, puede preguntar "¿Cuándo es apropiado crear un archivo de encabezado?"

voy a sugerir lo siguiente, donde el término "módulo de código" es un grupo (por lo general un directorio) de uno o más archivos relacionados .c:

  1. crear un encabezado de interfaces/definiciones públicas que debe estar disponible para otros módulos de código.
  2. Cree un encabezado para interfaces/definiciones privadas que deben compartirse dentro de un módulo de código pero no compartirse con otros módulos de código.

Esos son los únicos archivos de encabezado que debería necesitar. Si no se requieren ninguno de estos, entonces no necesita un encabezado.

A algunos codificadores les gusta separar artificialmente prototipos/macros/typedefs/etc en un .h separado de los globales/funciones en su .c. Recomiendo en contra de este enfoque y sugiero tener toda la funcionalidad relacionada en un solo archivo. A continuación, cambie a los encabezados cuando sea necesario, aquellos elementos que sean absolutamente necesarios para evitar que extern en otros archivos .c.

Cuestiones relacionadas