2010-05-26 6 views
-1

comment utiliser une variable définie dans un en-tête et les utiliser dans plusieurs fichiers source en utilisant extern. Je reçois une erreur de définition multiple.variable externe

+5

Est-ce une question C# ou C? – Oded

+3

C# ne sais pas "en-têtes" et vous ne pouvez pas définir de variables sans une classe dans C#. c'est une question c ou C++. – Jack

+0

Je l'ai modifié de C# à C, mais il peut s'agir de C++ pour tout ce que nous savons. – reinierpost

Répondre

9

Une bonne règle à suivre est: "Ne pas définir choses dans les fichiers d'en-tête". Déclarez tout ce que vous voulez, mais les définitions doivent être limitées aux non-têtes. Une déclaration est simplement une notification que quelque chose existe. Une définition définit réellement ce que c'est.

La raison d'être de cette directive est d'empêcher exactement la situation que vous voyez: les objets sont définis deux fois (ou plus) car les fichiers d'en-tête sont inclus dans plusieurs unités de compilation.

Pour éviter cela, vous pouvez utiliser quelque chose comme:

myprog.h: 
    extern int myVar;  // a declaration. 

myprog.c: 
    #include "myprog.h" 
    int myVar = 7;  // a definition. 

otherbit.c: 
    #include "myprog.h" 
    int fn (void) { 
     myVar = 12; 
     return myVar; 
    } 

La définition ci-dessus ne finissent dans myprog.o, vous ne serez pas en obtenir une copie en otherbit.o pour vous causer des problèmes au moment de la liaison. Laisser de côté cette bonne encapsulation rendrait ces variables globales une très mauvaise idée, c'est ainsi que je le ferais.

Le encapsulé façon de le faire serait quelque chose comme ceci:

myprog.h: 
    int getMyVar (void); 
    void setMyVar (int); 

myprog.c: 
    #include "myprog.h" 
    static int myVar = 7; 
    int getMyVar (void) { return myVar; } 
    void setMyVar (int n) { 
     // Error checks on n here. 
     myVar = n; 
    } 

otherbit.c: 
    #include "myprog.h" 
    int fn (void) { 
     setMyVar (12); 
     return getMyVar(); 
    } 

Encapsulation est essentiellement cacher des informations. Cela signifie que vous devez exposer comme peu de votre travail intérieur pour faire le travail, de peur que vous vous ouvriez la possibilité d'autres codes se faufiler sous les couvertures et invalider vos hypothèses (voir ci-dessous) ou le rendre plus difficile à changez vos fonctionnements intérieurs plus tard.

Un exemple classique est si vous voulez que la variable myVar soit limitée à la plage comprise entre 0 et 359 inclusivement (disons un angle). Avec l'encapsulation, vous pouvez simplement utiliser:

void setMyVar (unsigned int n) { myVar = n % 360; } 

et jamais à vous soucier de ce être invalide. Vous pouvez supposer sans risque, la corruption de mémoire de côté, que myVar sera toujours dans la fourchette désirée. Vous ne voudriez pas avoir cette certitude si une certaine rogue de code utilisateur pourrait venir faire juste:

myVar = 32767; 

sans que vous le sachiez. Vous devez soit répondre à des valeurs en dehors de votre gamme désirée ou le forcer à la plage valide au début de toutes vos fonctions:

myVar = myVar % 360; 

C'est une mauvaise pratique de codage, et tout à fait inutile.

+0

+1 pour les exemples propres et l'approche de programmation – INS

+0

Oui, Merci paxdiablo pour votre réponse. Cela m'a beaucoup aidé. –

Questions connexes