2009-06-06 12 views
4

Lors de la lecture du code source de la bibliothèque, je vois qu'il y a .c et .h fichiers du même nom. Dans la source principale, le fichier .h est inclus mais pas le fichier .c. Lorsque je regarde le code dans le fichier .h, il n'a pas non plus #include le fichier .c du même nom. Est-ce que je manque quelque chose? Est-ce que le compilateur inclut automatiquement un fichier .c lorsqu'un fichier .h du même nom est #include 'd?Comment lier les fichiers .c et .h du même nom?

Répondre

6

Non. Il n'est pas nécessaire d'inclure les fichiers .c dans les fichiers .h. Les fichiers .h ne sont normalement pas transmis directement au compilateur, mais leur seul but est d'être inclus dans d'autres fichiers.

Habituellement, il est quelque chose comme:

"a.c" includes "a.h" 
"b.c" includes "c.h" 

Vous compilez "a.c" et "b.c" et lier les fichiers de sortie.

4

Le fichier .h contient les déclarations des fonctions dans le fichier .c. Ces déclarations sont requises par d'autres fichiers .c qui souhaitent utiliser la fonctionnalité d'un autre fichier .c. Les fichiers .c ne sont donc jamais inclus dans les fichiers .h.

Chacun des fichiers .c est compilé dans un fichier objet et tous ces fichiers objets sont ensuite liés ensemble dans des bibliothèques ou des applications.

8

Les fichiers .h typiques servent de "table des matières" pour le fichier .c, y compris des éléments tels que les prototypes de fonction, les typedefs et autres. Les programmes incluent le .h afin qu'ils connaissent les fonctions et les types.

Les fichiers .c sont compilés séparément et produisent des fichiers objet (.o ou .obj) qui contiennent le code réel.

Les fichiers objets sont ensuite liés au programme principal via un fichier Makefile, Project ou une méthode similaire. Ensuite, les fichiers objets sont liés au programme principal, produisant un ensemble fonctionnel. Dans le cas des bibliothèques, est le aucun programme principal. Les fichiers objets sont rassemblés et mis dans un format spécial (pour les bibliothèques statiques ou dynamiques). Tout programme utilisant la bibliothèque inclurait le .h comme ci-dessus, et un lien vers la bibliothèque.

1

Le préprocesseur ne fait rien de magique.

Pour inclure quelque chose dans un dossier accessible (difficile à faire avec vos propres en-têtes)

#include <foo.h> 

ou pour inclure quelque chose dans le même répertoire de compilation

#include "foo.h" 

Tout ce qu'il faut-il le texte de foo.h et branchez-le directement à la sortie. gcc a.c -E affichera ce à quoi il ressemble après le prétraitement.

C'est un processus «stupide» en ce sens que l'écriture de votre propre programme qui traitera correctement #include est une sorte d'exercice trivial.

7

Il n'y a pas de magie. Quand un programme C est compilé, il y a deux étapes majeures.D'abord, chaque unité de compilation individuelle est compilée dans son isolation. (Une unité de compilation est essentiellement un fichier .c, plus tout ce qu'il contient). À ce stade, il ne sait rien de ce qui est contenu dans les autres fichiers .c, ce qui signifie qu'il ne peut pas générer un programme complet. Qu'est-ce qu'il peut faire est de générer du code avec quelques "remplir les blancs" des taches. Si, depuis foo.c, vous appelez une fonction déclarée dans bar.h et définie dans bar.c, alors le compilateur peut seulement voir que la fonction existe. Il est déclaré dans bar.h, donc nous devons supposer que la définition complète existe quelque part. Mais parce que cette définition est à l'intérieur d'une autre unité de compilation, nous ne pouvons pas encore la voir. Ainsi, le compilateur génère du code pour appeler la fonction, avec une petite note disant "remplir l'adresse de cette fonction une fois qu'elle est connue".

Une fois que chaque unité de compilation a été compilée de cette manière, il vous reste un tas de fichiers objets (typiquement .o si compilés par GCC, et .obj si vous utilisez MSVC), contenant ce genre de "remplir le code "blanc".

Maintenant, l'éditeur de liens prend tous ces fichiers objet, et essaie de les fusionner ensemble, ce qui lui permet de remplir les blancs. La fonction pour laquelle nous avons généré un appel ci-dessus peut maintenant être trouvée, ainsi nous pouvons insérer son adresse dans l'appel.

Ainsi, rien de spécial ne se produit si un fichier .c a le même nom qu'un fichier .h. C'est juste une convention pour aider les humains à comprendre ce qu'il y a dans chaque fichier.

Le compilateur s'en fout. Il prend juste chaque fichier .c, plus tout ce qu'il contient, et le compile dans un fichier objet. Et puis l'éditeur de liens fusionne tous ces fichiers objet en un seul exécutable.

1

Il y a un peu de fausse appellation dans votre question. Vous compilez les fichiers * .h et, sans tenir compte des inlines, vous liez les fichiers * .c.

Si vous allez revenir à l'essentiel, vous pouvez dire que:

  • le fichier « .h » est votre interface à la bibliothèque, à savoir ce que vous devez compiler contre et
  • la mise en correspondance *. Le fichier c est l'implémentation de ce que vous avez l'intention de faire.

Ainsi, à titre d'exemple:

  1. un add_integers.h de fichier déclare que la fonction, disons addInts(), qui prend deux entiers et retourne un entier qui est la somme des deux, et
  2. un fichier add_integers.c (pp) fournit l'implémentation de la fonction addInts() qui utilise un algorithme qui prend deux entiers, les additionne et renvoie les résultats.

L'implémenteur de la fonction addInts() est libre de modifier le logiciel qui implémente la fonction addInts(). Si l'interface de la fonction addInts() n'est pas modifiée du tout (ie addInts.h n'est pas du tout modifiée), alors une nouvelle bibliothèque partagée contenant l'implémentation modifiée de la fonction addInts est libre d'être distribuée sans que les gens aient à recompiler avec la nouvelle version de la bibliothèque addInts.

Wow! Pourquoi la lecture de cette explication ressemble-t-elle à Danny Kaye et "The Vessel with the Pessel"?

Vous aimerez peut-être jeter un oeil au travail de Bertrand Meyer avec Eiffel et "Design by Contract".

0

Si je veux créer une bibliothèque statique en C ou C++, je mettrai mes prototypes de fonctions dans les codes .h et les fonctions réelles dans le fichier .c ou .cpp. Après que je compilé mon Cpp pour faire un .lib

Pour lier mon .h à mon .lib j'écris cette commande préprocesseur dans le .h

#pragma comment (lib, "theNameOfTheLibFile.lib") 

Après que si je l'inclus dans .h un programme, mon programme sait où trouver la bibliothèque correspondante.

Questions connexes