web-dev-qa-db-fra.com

Dois-je compiler les fichiers d'en-tête dans un programme C?

Parfois, je vois quelqu'un compiler un programme C comme ceci:

gcc -o hello hello.c hello.h

Comme je le sais, nous devons simplement placer les fichiers d’en-tête dans le programme C comme:

#include "somefile"

et compilez le programme C: gcc -o hello hello.c.

Quand devons-nous compiler les fichiers d'en-tête ou pourquoi?

47
yuliu

Premièrement, en général:

Si ces fichiers .h Sont bien des fichiers d’en-tête typiques de style C (au lieu d’être quelque chose de complètement différent qui porte simplement le nom de l’extension .h), Alors non, il n’ya aucune raison de "compiler" "ces fichiers d’en-tête sont indépendants. Les fichiers d'en-tête sont destinés à être inclus dans les fichiers d'implémentation et ne sont pas transmis au compilateur en tant qu'unités de traduction indépendantes.

Etant donné qu'un fichier d'en-tête typique ne contient généralement que des déclarations pouvant être répétées en toute sécurité dans chaque unité de traduction, il est parfaitement normal que la "compilation" d'un fichier d'en-tête n'ait aucune conséquence néfaste. Mais en même temps, rien ne sera utile.

Fondamentalement, compiler hello.h En tant qu'unité de traduction autonome équivalente à la création d'un fichier dummy.c Dégénéré comprenant uniquement la directive #include "hello.h", Et alimenter ce fichier dummy.c Vers le compilateur . Cela compilera, mais cela ne servira à rien.


Deuxièmement, spécifiquement pour GCC:

De nombreux compilateurs traiteront les fichiers différemment en fonction de l'extension du nom de fichier. GCC applique un traitement spécial aux fichiers portant l'extension .h Lorsqu'ils sont fournis au compilateur sous forme d'arguments de ligne de commande. Au lieu de la traiter comme une unité de traduction normale, GCC crée un fichier en-tête précompilé pour ce fichier .h.

Vous pouvez lire à ce sujet ici: http://gcc.gnu.org/onlinedocs/gcc/Precompiled-Headers.html

C’est donc la raison pour laquelle vous pourriez voir les fichiers .h Directement alimentés vers GCC.

31
AnT

Bon, comprenons la différence entre code actif et code passif.

Le code actif est l’implémentation de fonctions, procédures, méthodes, c’est-à-dire les éléments de code devant être compilés en code machine exécutable. Nous le stockons dans des fichiers .c et nous sommes sûrs de le compiler.

Le code passif n’est pas en train de s’exécuter lui-même, mais il devait expliquer aux différents modules comment communiquer entre eux. En général, les fichiers .h ne contiennent que des prototypes (en-têtes de fonctions), des structures.

Les macros constituent une exception, car elles peuvent contenir formellement des éléments actifs, mais vous devez comprendre qu'elles utilisent très tôt le processus de création (prétraitement) avec une simple substitution. Au moment de la compilation, les macros sont déjà substituées à votre fichier .c.

Une autre exception concerne les modèles C++, qui devraient être implémentés dans des fichiers .h. Mais voici l'histoire similaire aux macros: elles sont remplacées au début (instanciation) et formellement, chaque instanciation est un autre type.

En conclusion, je pense que si les modules sont correctement formés, nous ne devrions jamais compiler les fichiers d'en-tête.

6
Alexander Mihailov

Dans certains systèmes, les tentatives d’accélération de l’assemblage des fichiers '.c' entièrement résolus appellent le pré-assemblage des fichiers d’inclusion "compilation des fichiers d’en-tête". Cependant, il s’agit d’une technique d’optimisation qui n’est pas nécessaire pour le développement du C réel.

Une telle technique calcule essentiellement les instructions include et conserve un cache des inclus aplatis. Normalement, la chaîne d’outil C coupe et colle récursivement dans les fichiers inclus, puis transmet l’élément entier au compilateur. Avec un cache d'en-tête pré-compilé, la chaîne d'outils vérifiera si l'une des entrées (définitions, en-têtes, etc.) a été modifiée. Sinon, il fournira les extraits de fichier texte déjà aplatis au compilateur.

Ces systèmes étaient destinés à accélérer le développement; Cependant, beaucoup de ces systèmes étaient assez fragiles. À mesure que les ordinateurs accéléraient et que les techniques de gestion du code source changeaient, moins de pré-compilateurs d'en-tête étaient réellement utilisés dans le projet commun.

Jusqu'à ce que vous ayez réellement besoin d'optimisation de la compilation, je vous recommande vivement d'éviter les en-têtes de pré-compilation.

1
Edwin Buck

Je pense que nous avons besoin de prétraiter (peut-être pas appeler la compilation) le fichier head. À ma connaissance, pendant la compilation, le fichier head devrait être inclus dans le fichier c. Par exemple, dans test.h nous avons

typedef enum{
    a,
    b,
    c
}test_t

et dans test.c nous avons

void foo()
{
    test_t test;
    ...
}

pendant la compilation, je pense que le compilateur mettra le code dans le fichier head et le fichier c ensemble et le code dans le fichier head sera prétraité et remplacera le code dans le fichier c. En attendant, nous ferions mieux de définir le chemin d’inclusion dans le fichier makefile.

1
How Chen