Définition de la Variable dans les fichiers d'en-tête

Mes connaissances de base de C et le processus de compilation est devenu rouillé dernièrement. J'essayais de trouver la réponse à la question suivante, mais je n'ai pas pu connecter les bases de la compilation, du lien et de la phase de pré-traitement. Une recherche rapide sur Google n'aide pas beaucoup non plus. Alors, j'ai décidé de venir à la source ultime de la connaissance :)

je sais: les Variables ne doivent pas être définies dans le .h fichiers. Son ok pour les déclarer y.

Pourquoi: parce qu'un fichier d'en-tête peut être inclus à partir de plusieurs endroits, redéfinissant ainsi la variable plus d'une fois (Linker donne l'erreur).

Possible de travailler autour de: utilisez header-guards dans les fichiers d'en-tête et définissez variable dans cela.

Est-ce vraiment une solution: Non. Parce que les header-guards sont pour la phase de prétraitement. C'est-à-dire compilateur que cette partie a été déjà inclus et ne comprennent pas une fois de plus. Mais notre erreur de définition multiple vient dans la partie linker - beaucoup après la compilation.

tout cela m'a déconcerté sur la façon dont le prétraitement et le travail de liaison. Je pensais que le prétraitement n'inclurait tout simplement pas le code, si le symbole de garde de l'en-tête a été défini. Dans ce cas, la définition multiple d'un problème variable ne devrait-elle pas aussi être résolue?

que se passe-t-il si ces directives de prétraitement empêchent le processus de compilation de se redéfinir? les symboles sous header guards, mais le linker obtient encore plusieurs définitions du symbole?

24
demandé sur Brian Tompsett - 汤莱恩 2010-02-07 15:27:37

4 réponses

Header guard vous protège des inclusions multiples dans un fichier source unique, et non de plusieurs fichiers source. Je suppose que votre problème vient du fait que vous ne comprenez pas ce concept.

ce n'est pas que les pré-processeurs préservent le temps de compilation de ce problème. En fait, pendant 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 lien lorsque le linker essaie de résoudre le symbole definitons, il obtient confus voir plus d'une définition le casuing pour signaler l'erreur.

24
répondu Jay 2010-02-07 13:05:30

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

var.h fichier:

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

Puis .c fichier (généralement l'un contenant le main()):

#define DEFINE_GLOBALS
#include "var.h"

le reste des fichiers source inclut juste " var.h" normalement.

notez que DEFINE_GLOBALS n'est pas un header guard, mais permet plutôt de déclarer/définir les variables selon qu'elles sont définies ou non. Cette technique permet une copie du déclarations / définitions.

26
répondu Richard Pennington 2010-02-07 12:50:06

Vous en avez deux .c fichiers. Ils ont compilé séparément. Chacune comprend votre fichier d'en-tête. Lorsque. Chacun reçoit une définition. Ils sont en conflit au moment de la liaison.

la solution conventionnelle est:

#ifdef DEFINE_SOMETHING
int something = 0;
#endif

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

10
répondu bmargulies 2010-02-07 12:48:37

en-Tête de gardes arrêtent un fichier d'en-tête inclus plusieurs fois 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 en deux ou plusieurs unités de traduction.

8
répondu 2010-02-07 12:51:58