2010-10-04 10 views
2

Une autre question de débutant; Est-ce un mauvais goût d'utiliser beaucoup de variables globales dans C? Je suppose que la réponse est probablement oui, d'un autre côté, utiliser la fonction principale ou une autre fonction comme "base-function" pour stocker des pointeurs/valeurs avec une portée globale crée tout un désordre avec des pointeurs vers des pointeurs etc ... pensées?Variables globales dans C

+3

Vous devez accepter les réponses. Je vois que vous n'avez pas fait cela pour votre question précédente. Si vous trouvez une réponse qui fonctionne pour vous, vous devriez l'accepter. –

Répondre

3

Un problème avec les variables globales est que, peu importe où elles sont utilisées, vous ne pouvez pas avoir referential transparency. Et c'est une bonne chose de savoir que, compte tenu de certaines entrées, une fonction produira certaines sorties pour plusieurs raisons.

This page is a good resource pour plusieurs autres raisons pour lesquelles les variables globales sont également mauvaises.

0

Bien que C vous donne la totale liberté de déclarer tout ce qui est global, il vous aidera à coder et à entretenir si vous pensez en termes de "abstract data type" qui peut également être implémenté dans les langages procéduraux. Essentiellement, au lieu de rendre toutes les données comme globales statiques à tous les modules, vous pouvez rendre les données globales dans un module particulier.

1

Utilisez des variables globales si c'est extrêmement nécessaire. Si vous avez quelque chose qui est nécessaire sur une portée mondiale, alors n'hésitez pas.

2

Habituellement, la plupart des programmeurs s'attendent à ce que les fonctions soient pure, ce qui signifie que la sortie d'une fonction sera complètement déterminée par son entrée. En leur donnant des états, vous pouvez introduire beaucoup de confusion pour les autres qui utiliseront votre code. Cela renvoie aux variables static déclarées dans les fonctions.

Et pour les variables globales réelles (celles déclarées en dehors des fonctions), c'est ce que Ruel a dit. Soyez prudent, même si vous êtes sur le multithreading.

+0

+1 La même chose s'applique aux variables des membres de la classe. –

1

Rectifier la situation causée par un désordre de globals est comme normaliser la conception d'un schéma de base de données relationnelle.

Il est toujours possible de regrouper toutes les globales en une seule grande structure et de passer cette structure autour. Mais alors, quel est le point?

Vous souhaitez les regrouper en structures et vous commencez à les découvrir, "hé j'ai aussi besoin de cette information dans l'autre structure car une fonction idiote en a besoin." Alors vous avez pensé que vous avez résolu le problème en fusionnant les deux structures. Ensuite, vous avez trouvé que finalement, vous êtes toujours coincé avec un gros morceau de struct.

Pourquoi? Parce que comme la normalisation de base de données, votre normalisation de structure doit être faite de concert, en complot avec les processus (aka vos fonctions). Vous devez construire une relation d'entité à propos de vos informations. Même si vous n'écrivez pas en utilisant un langage oop, vous devez toujours utiliser des méthodes d'analyse de systèmes proches de oop. La différence entre un programmeur-analyste et un programmeur ordinaire est qu'un programmeur-analyste effectue une analyse rigoureuse des données et des processus du projet. Considérant que, le programmeur plain vanilla fait la programmation happy-go-lucky.

Par exemple, je voudrais écrire une routine pour contrôler les imprimantes dans l'entreprise. Il y a

  • vieux téléscripteurs ruban impact (vache sacrée!),
  • matrice de points (ils utilisent encore ceux?),
  • couleur-jets,
  • gris-jets
  • ,
  • lasers gris et,
  • couleur lasers
  • combos fax/numérisation des jets et des lasers.

Et ce sont les fonctionnalités

  • trouver une imprimante appropriée pour une demande d'emploi
  • réacheminer un travail à partir d'une imprimante a échoué
  • une demande d'emploi peut à partir d'un calendrier, un ordinateur de bureau ou d'un serveur de fax
  • acheminer une sortie de numérisation vers un serveur de fax
  • numérisation de l'encre, niveaux de pigment pour remplacement
  • pour les types de ruban obsolètes, ruban remplacement
  • prédire
  • maintenir le calendrier d'entretien

L'approche simple est d'avoir toutes les informations placées dans un immense bassin de GLOBALS puis les extern partout. L'avantage est que vous avez la liberté d'écrire des fonctions sans restriction - restreint seulement par votre capacité à vous souvenir où sont toutes les variables. Ou la capacité de quelqu'un d'autre à les trouver. Ou, vous pourriez vous simplifier la vie et apprendre les astuces simples de la normalisation des entités. Rappelez-vous, l'entité n'est pas seulement les données mais aussi les processus/fonctions. À la fin d'un tel exercice, vous commencerez à vous demander avec étonnement comment vous auriez pu survivre jusqu'à maintenant dans la vie sans un langage OOP comme C++. Permettez-moi d'illustrer ci-dessous avec une implémentation simpliste (peut-être incomplète). Lorsque vous planifiez votre projet en salle d'urgence et que vous le documentez, cela facilite grandement la programmation et l'amélioration. En cette ère de l'ingénierie agile, vous devez être capable de libérer une implémentation partielle utilisable d'un projet. par exemple, vous raconterait votre gestionnaire de projet, les étapes suivantes

  • Semaine1: Utilisable routage pour imprimantes à jet d'encre et laser
  • Semaine2: Utilisable routage pour imprimantes d'impact archaïques
  • Semaine3: travaux de numérisation utilisables
  • week5-7: travaux de télécopie utilisables
  • semaine8: emploi Semiboulange réacheminer
  • week9: 90% emploi cuit réacheminer
  • week9- 11: maintenance à mi-cuisson

Avec le schéma de vos informations et processus, vous aurez une idée claire de ce qui constitue une version utilisable et de ce qu'il faut faire lors de la prochaine itération. Avec un schéma bien planifié, vous trouveriez émotionnellement impossible d'utiliser des globals. Vous auriez même alors un schéma de globals plutôt que de les avoir déstructurés. Réserver une structure globale pour une information qui nécessite absolument et nécessairement un point d'accès unique - comme un pool de bases de données, des indicateurs de démarrage pour éviter de démarrer des processus déjà démarrés, etc.Puis, à moins que vous n'écriviez du code noyau ou intégré, vous devriez très bientôt passer en C++, c'est garanti.

struct Printer{ 
    id, 
    printType, 
    location, 
    *maintenance, 
    *driver 
} 

struct Job{ 
    type, 
    requestor, 
    location 
} 

struct Location{ 
    building, 
    floor, 
    suite, 
    lane 
} 

struct PrintType{ 
    ink, 
    colour 
} 

struct JobStatus{ 
    job, 
    location, 
    endStatus 
} 

struct Maintenance{ 
    inkLevel, 
    schedule 
} 

union InkLevel{ 
    HPDeskJetInk, 
    HPLaserJetInk, 
    OlivettiFabric, 
    BrotherCellophane, 
    etc, etc 
} 

enum Ink{ 
    FABRICImpact, 
    CELLOPHANEImpact, 
    INKJet, 
    LASER 
} 

enum Colour{ 
    GREY, 
    COLOUR 
} 

enum EndStatus{ 
    PRINTING, 
    COMPLETED, 
    FAILED, 
    REROUTED 
} 

/* print will look at Job to determine the appropriate location */ 
JobStatus* print(job); 

/* a callback to requestor indicating completion status */ 
JobStatus* printCallback(); 

/* a fax send event detected and fax function will find the appropriate server for the Job */ 
JobStatus* fax(job); 

/* a photocopy to file job */ 
JobStatus* scan(job); 

Maintenance* maintain(Printer); 
-6

Il est mauvais d'utiliser des variables globales dans n'importe quelle langue.

+1

omg lawlz !!!!!! –

+0

Wow, je ne savais pas que j'aurais autant de contrecoup de la part des amateurs de variables globales anonymes. –