Plusieurs bibliothèques de définition et d’en-tête seulement

J’ai un programme C avec plusieurs fichiers c et h. J’ai décidé de faire une partie du programme ‘en-tête uniquement’ alors j’ai déplacé le code de c en h. Maintenant, j’ai de multiples problèmes de définition et je ne sais pas pourquoi. par exemple:

main.c includes utils.h vector.c includes utils.h 

J’ai tout déplacé dans utils.c à utils.h (et bien sûr supprimé utils.c du projet). utils.h commence par

 #ifndef UTILS_H_ #define UTILS_H_ // and end with: #endif 

Pour être sûr que ma garde était unique, j’ai essayé de la changer (par exemple: UTILS718171_H_) mais cela ne fonctionnait pas.

Pourtant, le compilateur se plaint:

 /tmp/ccOE6i1l.o: In function `compare_int': ivector.c:(.text+0x0): multiple definition of `compare_int' /tmp/ccwjCVGi.o:main.c:(.text+0x660): first defined here /tmp/ccOE6i1l.o: In function `compare_int2': ivector.c:(.text+0x20): multiple definition of `compare_int2' /tmp/ccwjCVGi.o:main.c:(.text+0x6e0): first defined here /tmp/ccOE6i1l.o: In function `masortingx_alloc': ivector.c:(.text+0x40): multiple definition of `masortingx_alloc' /tmp/ccwjCVGi.o:main.c:(.text+0x0): first defined here ... 

Le problème pourrait être quelque chose du genre: tous les fichiers c sont compilés et obtiennent leur propre version du code, ce qui pose problème au niveau du couplage, mais honnêtement, je ne sais pas du tout comment résoudre ce problème.

Si vous définissez vos variables dans votre fichier d’en-tête et incluez l’en-tête dans plusieurs fichiers c, vous obtiendrez une erreur de définitions multiples car vous rompez la règle de définition unique (ODR) , qui stipule qu’il ne doit exister qu’une seule définition dans une unité de traduction. (fichiers d’en-tête + fichier source).

La solution est:
Vous devez définir les entités que vous obtenez Plusieurs erreurs de définition pour une seule fois.
Pour les fonctions:
Déclarez les prototypes de fonction dans le fichier d’en-tête (que vous incluez dans d’autres fichiers source) et définissez la fonction dans un et un seul fichier source.
Pour les variables globales:
Vous déclarez la variable extern dans le fichier d’en-tête (que vous incluez dans d’autres fichiers source), puis définissez la variable dans un et un seul fichier source.

Vous manquez le sharepoint la construction #ifndef _FOO_H / #define _FOO_H / #endif. Cela protège uniquement contre les inclusions multiples dans un fichier. Par exemple, ils protègent contre ceci:

foo.h:

  #ifndef _FOO_H #define _FOO_H /* some C stuff here */ #endif /* _FOO_H */ 

foo.c:

  #include  #include  ... 

bar.h:

  #include  ... 

notez que foo.c et bar.h incluent tous deux foo.h; ici, le #ifdef _FOO_H / #define _FOO_H / #endif protège contre cette double inclusion dans foo.c (le foo.h inclus dans bar.h ne redéfinit pas le contenu)

Maintenant la prochaine partie.

Pourquoi voudriez-vous déplacer l’implémentation de la fonction d’utils.c à utils.h? Aussi, pourquoi avez-vous décidé de le rendre “en-tête uniquement”?

Vous pouvez le faire si votre compilateur prend en charge static inline fonctions en static inline . mais même dans ce cas, ce n’est PAS recommandé, car il est plus que probable que cela rendra votre programme inutilement gonflé car il est probable que vos fonctions util sont assez complexes et ne peuvent de toute façon pas être alignées.

Donc, revenez à la construction utils.c et utils.h que vous aviez auparavant et qui, je suppose, fonctionnait et appréciait le logiciel.

Vous violez la règle d’une définition. Chaque fonction doit être définie avec précision une fois , pendant que vous finissez par la définir dans chaque unité de traduction .

Vous ne pouvez simplement pas faire quelque chose comme ça:

 // header.h void foo() { } // file1.c #include "header.h" // file2.c #include "header.h" 

La seule vraie solution est de déclarer void foo(); dans l’en-tête et définissez- le une seule fois (généralement dans un foo.c dédié). Il en va de même pour les variables globales, qui doivent être déclarées en tant que extern dans l’en-tête et définies dans le fichier source.

Inclure les gardes n’a rien à voir avec cela. Ils servent uniquement à empêcher l’inclusion de soi récursive ou l’inclusion multiple redondante au sein d’une unité de traduction .

Si vous indiquez que les fonctions utils.h doivent être “copiées” à chaque endroit où elles sont utilisées, utilisez simplement static fonctions static dans l’en-tête. ( static inline dans C99)