Pourquoi mes gardes de compilation n’empêchent-ils pas les inclusions de définitions multiples?

J’ai un fichier d’en-tête xh qui est inclus dans plusieurs fichiers sources * .c. Ce fichier d’en-tête a des variables de structure définies.

J’ai mis plusieurs protections de prévention d’inclusion au début du fichier d’en-tête comme suit:

#ifndef X_H #define X_H ... .. //header file declarations and definitons. #endif//X_H 

En construisant, j’obtiens des erreurs de lieur liées à plusieurs définitions. Je comprends le problème.

  1. Un garde de prévention des inclusions multiples en haut du fichier d’en-tête, comme je l’ai fait, empêchera-t-il plusieurs inclusions du fichier d’en-tête xh et évitera-t-il ainsi plusieurs définitions des variables contenues dans xh?

  2. #pragma fois, #pragma ne fonctionne pas sur ce compilateur, alors quelle est la solution? Quelqu’un avait posté cette réponse à une question similaire. Cela ne semble pas fonctionner pour moi. Comment fonctionne cette solution?

Si l’éditeur de liens se plaint, cela signifie que vous avez des définitions plutôt que de simples déclarations dans votre en-tête. Voici un exemple de ce qui pourrait être faux.

 #ifndef X_H #define X_H int myFunc() { return 42; // Wrong! definition in header. } int myVar; // Wrong! definition in header. #endif 

Vous devriez diviser cela en fichier source et en-tête comme ceci:

Entête:

 #ifndef X_H #define X_H extern int myFunc(); extern int myVar; #endif 

C Source:

 int myFunc() { return 42; } int myVar; 

L’utilisation de include gardes empêche une unité de compilation d’inclure l’en-tête deux fois. Par exemple, si l’en-tête Bh comprend Ah et B.cpp comprend Ah et Bh, tout ce qui vient de Ah sera déclaré deux fois dans la compilation B.cpp si vous n’utilisiez pas de gardes inclus.

Vos gardes comprennent empêcher que cela se produise, tout va bien jusqu’à maintenant.

Mais vous obtenez plusieurs définitions au moment de la liaison, c’est-à-dire que deux unités de compilation définissent la même chose, cela signifie probablement que vous avez une vraie définition dans votre en-tête, utilisez extern pour toutes les variables, assurez-vous que les fonctions sont en ligne ou définies dans le fichier cpp.

Les gardes d’en-tête ne conviennent que pour une seule unité de compilation, c’est-à-dire un fichier source. S’il vous arrive d’inclure un fichier d’en-tête plusieurs fois, peut-être parce que tous les en-têtes inclus dans main.c incluent à leur tour stdio.h alors les gardes vous aideront.

Si vous avez la définition d’une fonction f dans xh qui est incluse dans les util.c main.c et util.c , le util.c est comme copier / coller de la définition de f dans main.c lors de la création de main.o et de la même chose pour util.c pour créer util.o Ensuite, l’éditeur de liens se plaindre et cela se produit malgré vos gardes d’en-tête. Avoir plusieurs instructions #include "xh" dans main.c est bien sûr possible grâce à ces gardes.

Si les fonctions ne sont pas volumineuses, vous pouvez utiliser “inline” avant elles et l’éditeur de liens ne se plaindra pas.

L’utilisation d’une protection d’inclusion multiple empêche les erreurs du compilateur , mais vous obtenez une erreur de l’éditeur de liens. Avez-vous des définitions de données dans le fichier d’en-tête qui n’utilisent pas extern ?

Peut-être que X_H est déjà défini ailleurs? Je viens de rencontrer ce problème, où Xlib définit X_H dans / usr / include / X11 / Xh

Pour vérifier, vous pouvez appeler gcc -dM -E (si vous utilisez gcc), par exemple dans le système de construction que j’utilise qui fonctionne avec CC=gcc CFLAGS="-dM -E" make Si le fichier de sortie contient #define X_H même si vous le supprimez de votre fichier (utilisez Y_H par exemple), il est déjà défini en dehors de votre code source.