Définition de variable dans les fichiers d’en-tête

Ma connaissance très élémentaire du processus de compilation et de C s’est rouillée récemment. J’essayais de comprendre la réponse à la question suivante mais je ne pouvais pas associer les bases de la compilation, du lien et de la phase de pré-traitement. Une recherche rapide sur Google n’a pas beaucoup aidé non plus. J’ai donc décidé de venir à la source ultime de connaissances 🙂

Je sais: Les variables ne doivent pas être définies dans les fichiers .h. Son ok pour les déclarer là.

Pourquoi: puisqu’un fichier d’en-tête peut être inclus à partir de plusieurs emplacements, redéfinissant ainsi la variable plus d’une fois (l’éditeur de liens donne l’erreur).

Solution possible: utilisez des gardes d’en-tête dans les fichiers d’en-tête et définissez-y une variable.

Est-ce vraiment une solution? Non, car les en-têtes sont destinés à la phase de prétraitement. C’est pour dire au compilateur que cette partie a déjà été incluse et ne l’incluez pas encore. Mais notre erreur de définition multiple se situe dans la partie de l’éditeur de liens – bien après la compilation.

Tout cela me laisse confus quant à la manière dont le prétraitement et la mise en relation fonctionnent. Je pensais que le prétraitement n’inclurait tout simplement pas le code, si le symbole de protection d’en-tête avait été défini. Dans ce cas, la définition multiple d’un problème de variable ne devrait-elle pas également être résolue?

Que se passe-t-il si ces directives de prétraitement empêchent le processus de compilation de redéfinir les symboles sous des en-têtes, mais l’éditeur de liens obtient toujours plusieurs définitions du symbole?

La protection d’en-tête vous protège contre plusieurs inclusions dans un seul fichier source, et non contre plusieurs fichiers source. Je suppose que votre problème provient de ne pas comprendre ce concept.

Ce ne sont pas les protecteurs de pré-processeur qui économisent pendant la compilation le problème. En fait, lors de la compilation, un seul fichier source est compilé dans un obj, les définitions de symboles ne sont pas résolues. Mais, en cas de liaison lorsque l’éditeur de liens essaie de résoudre les définitions de symboles, il est confus de voir plus d’une définition l’incriminer pour signaler l’erreur.

Une chose que j’ai utilisée dans le passé (quand les variables globales étaient en vogue):

fichier var.h:

... #ifdef DEFINE_GLOBALS #define EXTERN #else #define EXTERN extern #endif EXTERN int global1; EXTERN int global2; ... 

Ensuite, dans un fichier .c (généralement celui contenant main ()):

 #define DEFINE_GLOBALS #include "var.h" 

Le rest des fichiers source n’inclut que “var.h” normalement.

Notez que DEFINE_GLOBALS n’est pas une protection d’en-tête, mais permet plutôt de déclarer / définir les variables en fonction de sa définition. Cette technique permet une copie des déclarations / définitions.

Vous avez deux fichiers .c. Ils sont compilés séparément . Chacun comprend votre fichier d’en-tête. Une fois que. Chacun obtient une définition. Ils sont en conflit au moment de la liaison.

La solution conventionnelle est:

 #ifdef DEFINE_SOMETHING int something = 0; #endif 

Ensuite, vous # définissez DEFINE_SOMETHING dans un seul fichier .c.

Les gardes d’en-tête empêchent l’inclusion multiple d’un fichier d’en-tête dans la même unité de traduction (c’est-à-dire dans le même fichier source .c). Ils n’ont aucun effet si vous incluez le fichier dans plusieurs unités de traduction.