J'ai un fichier incluant avec plus de 100 variables globales. Il est utilisé dans une bibliothèque, mais certains programmes que je relie la lib afin d'accéder également aux globaux.
La façon dont il a été construit: p> i J'ai eu du mal à comprendre pourquoi le programmeur d'origine a fait que j'ai donc supprimé cela définissant des choses externes. Maintenant, je pense que je comprends la chose à propos de TU à l'aide de Stackoverflow:
1 ,
2 ,
3 . p> Maintenant, je comprends que je devrais définir les variables globales dans un fichier .C dans la bibliothèque et utiliser externe dans le fichier .h. Le problème est que je ne veux pas dupliquer du code. P> Dois-je revenir à ce #define extern Voodoo? p> p>
8 Réponses :
C'est un mauvais modèle de définir externe dans chaque fichier .c. Supprimer c'est probablement le meilleur, mais vous devez remplacer cette fonctionnalité en quelque sorte. Une approche est que vous pouvez utiliser un #define dans le fichier .C qui doit définir ces globaux. Cela définisse signalera à la .h à ne pas externe les variables globales.
Par exemple:
La bibliothèque .c fichier .C: p> les autres fichiers .c: p> foo_library.h: p > ou p> Ceci réduit la nécessité de définir la même chose dans chaque fichier source (sauf un) et aiderait à réduire les erreurs. Je ne l'appellerai pas non plus externe comme cela peut simplement causer de la confusion, car il peut ou non être "externe" p> p>
Je suis en désaccord que c'est un mauvais modèle: je sais que cela va à l'encontre de la sagesse perçue d'avoir les externes dans .h des fichiers, mais pour ce cas même, je ne peux penser à aucun autre inconvénient que d'avoir à écrire quelques définitions externes supplémentaires. Si vous trouvez la nécessité d'écrire des tonnes d'entre eux, votre code est un désordre (trop de variables globales) et vous devriez toujours penser à la manière dont vous les utilisez et où vous les utilisez, car ils peuvent causer des bugs très subtils. En utilisant un fichier .h, vous vous donnez une carte blanche pour utiliser des variables globales indiscriminantes.
Makis, vous vous confondez 2 choses ici; - le choix de conception d'utiliser des variables globales et des meilleures pratiques lorsque vous devez utiliser une variable globale. Il est clair que l'utilisation de variables globales est généralement une mauvaise idée, mais lorsque vous devez en utiliser un, utilisez la meilleure utilisation de son implémentation et c'est extern var code> Déclaration dans l'en-tête et
var code > Définition dans la droite
.c code> fichier. Tout autre modèle d'utilisation est faux.
Je serais peut-être manquant quelque chose, mais je ne vois aucune différence entre le code> #define code> trucsy et simplement à l'aide du mot-clé code> p>
Fondamentalement, vous devez déclarer les VARS dans un fichier .h et les définir dans un fichier .C. Ne considérez pas la duplication de code informatique - je pense que changer le point de vue est la meilleure chose à faire ici :). Vous pouvez écrire plus de lignes de code, mais elles seront lisibles: ré. P>
Je suis prêt à être que l'extérieur est placé dans la déclaration et les fichiers d'en-tête pour faire couper et coller la valeur JSUT qui plus facile à utiliser et d'avoir un Quant Visual qui a déclaré que la portée mondiale est visible. Cela dit, je frémise le merveilleux abus qui permet partout. Oh, les jours de Spaghetti Var Tracking ...
Eh bien, je fais cela pour dll_export et tel, mais c'est parce que M $ VC et GCC font différemment. En ce qui concerne les externes, je préfère vraiment simplement avoir un .h et un fichier .c pour eux. Comme je l'ai dit, c'est plus de code, mais j'aime la lisibilité. Peut-être que c'est juste une préférence personnelle, je ne sais pas. Encore une fois, étiez-moi pour ériter un code illisible, j'apprendais à programmer dans Brainfef * ck ou quelque chose de similaire :)
Cette chose même est la raison pour laquelle je spécifie des noms de variables mondiaux, même si je déteste la notation hongroise avec une vengeance. Selon le style du programme, j'utilise le préfixe "g" ou "g_" pour ceux-ci. Cela aide les inspections plus que vous ne pouviez croire.
+1 I Deuxièmement que je vais encore plus loin. Ne définissez jamais une variable globale dans un en-tête, jamais, pas d'exception, il n'appartient que la douleur et le chagrin. Inclure les fichiers doit être idempotent.
Peut-être que je manque quelque chose aussi, mais je Toujours strong> Utilisez des gardes d'inclusion sur tous les fichiers d'en-tête I Créer: FOO.H: P> #include "foo.h"
#include <stdio.h>
int main(int argc, char** argv)
{
printf("foo:%d\n",foo);
return 0;
}
Je pense que cette stratégie simple ne fonctionnera pas avec les bibliothèques et les programmes qui incluent le même fichier d'en-tête.
Je préfère beaucoup cela sur la méthode d'Aaron également énumérés ici. Avoir les définitions d'un dossier et que les déclarations d'une autre ont plus de sens pour moi et ressemblent à un modèle beaucoup plus commun.
Les gens, cela ne fonctionnera pas. Imaginez si je compile la bibliothèque et, à une date ultérieure, compilez un programme comprenant que .h fichier. Les deux auront les globaux sans externe. C'est la situation que je décris.
@Costi, Foo.c fait partie de la bibliothèque, les globaux sont dans la bibliothèque. Vos programmes incluront tous FOO.H - où les globaux sont définis externes. Les gardes d'inclusion permettront à chaque programme de construction séparément pour inclure FOO.H une fois. Pouvez-vous expliquer comment cela est cassé parce que je ne le vois pas.
Mes mauvais, les gars. Je vois maintenant que foo.c a "int foo = 0". Mais je vois toujours un problème avec cette approche: j'ai plus de 100 globaux et c'est beaucoup de dupliqué de code dans les fichiers .c et .h lib. Avec la solution d'Aaron, ils ne seront déclarés que dans le fichier .h.
@Costi: vrai je suppose. De quelques recherches rapides de "Cibliothèque C avec des variables globales", j'ai l'impression que les globaux dans une bibliothèque sont une mauvaise idée de toute façon. Si je le lisons correctement, si deux programmes d'exécution simultanément partagent le même ensemble de globaux ou avoir leurs propres copies, ne peuvent pas être invoqués et sont spécifiques au système d'exploitation, etc.
Je ne pense pas que les données soient partagées entre les processus d'exécution à l'aide de la même bibliothèque. Et, de toute façon, nous relions de manière statique à notre propre lib :)
@Costi: Si ce n'est pas votre bibliothèque, cela n'a pas de problème si les codes sont dupliqués. S'il s'agit de votre bibliothèque, vous devriez vraiment éviter d'utiliser ces nombreuses variables globales. Même la solution de Paul R est bien meilleure. James Morris donne la solution la plus standard.
+1. Vous ne devriez pas utiliser l'inclusion des fichiers d'en-tête pour inclure le "code" (par rapport aux définitions). Je sais que la ligne est floue ici, mais l'idée de quitter le mot clé externe offert efficacement la fonction d'en-tête, car la définition fonctionne, mais n'est qu'un sous-produit de la gestion des globaux «trop nombreux» (je sais que cela est subjectif, mais je 'm expliquer pourquoi ce modèle n'est pas aussi courant dans la nature.)
Le truc ici est que le fichier .h est utilisé de deux manières différentes - il est utilisé comme un fichier normal .h si tous les globaux sont déclarés Quoi qu'il en soit, il y a une solution quelque peu plus élégante - vous pouvez mettre Tous vos globaux dans une seule structure globale, par exemple p> - p> - p> alors puis quand vous devez faire référence à un global, c'est par exemple extern code> et il est également utilisé pour < em> définir em> les globaux eux-mêmes (sans
extern code>). C'est un hack moche mais vous pouvez comprendre pourquoi quelqu'un a estimé qu'il était nécessaire si vous avez un grand nombre de globaux (un signe sûr d'une très mauvaise conception de logiciels!).
globals.a code> au lieu de
A code>, ce qui pourrait sembler un inconvénient, mais cela est sans doute plus clair et plus gérable que de simplement avoir des globaux nus dispersés dans le code. P> p>
Vous avez raison et mettre ces globaux dans certaines structures est un todo. Il est même possible de leur donner des noms significatifs.
Bien que cela puisse être ennuyeux d'abord, il vous aide à éviter de taper la chose deux fois ou d'oublier d'inclure quelque chose dans un fichier .C du tout.
J'ai vu: avec foo.h étant: p>
L'utilisation de déclarations globales sur la fonction est inutile. Le semi-points après le deuxième #define déclarer code> est erroné.
En règle générale, n'utilisez pas de variables globales. Parfois, vous devez utiliser des variables statiques dans le fichier, mais il est préférable d'essayer de les éviter du tout:
Parfois, dans C, vous ne pouvez pas les éviter (surtout dans le code hérité par quelqu'un) mais le mieux est de les garder dehors. P>
Quant à la déclaration - Cela pourrait être utile dans ce cas: p>
Les choses macro sont stupides pour cela. Il suffit de mettre dans votre fichier d'en-tête, et dans un fichier .C .c (typiquement un avec le même nom que le fichier .h), mettez p> int myGlobal;
Cela devrait être la réponse acceptée. C'est la seule approche sain d'esprit. Tout autre prepprocesseur Acrobatic présenté dans les autres réponses est incorrect, ajoutant un bruit inutile dans le code.
Dans les grands programmes, il est très important de disposer d'une seule ligne de déclarer et de définir une variable globale. Par conséquent, l'approche macro décrite ci-dessus est la bonne façon de résoudre le problème.
// globals.h #ifndef GLOBALS_H #define GLOBALS_H #ifndef EXTERN #define EXTERN extern #endif EXTERN int i; #endif // globals.c #define EXTERN #include "globals.h"
Désolé de monter ces derniers temps, mais la réponse acceptée est la mauvaise approche. La réponse de Frederik Slijkerman est la bonne. Seules les déclarations dans les fichiers .h et les définitions dans les fichiers .c.
extern var code> est une déclaration, sans
extern code> c'est une définition. Placez la définition de la variable dans le module (c'est-à-dire un fichier .c) il est logiquement (sémantiquement) une partie de. Inversement, jamais i> Utilisez un
extern var code> dans un fichier .c.