Visibilité de variables c [Résolu]

Signaler
Messages postés
223
Date d'inscription
mercredi 31 mai 2006
Statut
Membre
Dernière intervention
5 mai 2014
-
Messages postés
966
Date d'inscription
samedi 3 avril 2004
Statut
Membre
Dernière intervention
4 mars 2010
-
Bonjour,

Voici mon problême :
Mon programme possède un main et 3 modules : main.cpp, m1.cpp, m2.cpp, m3.cpp
main.cpp inclut m1.h, m2.h et m3.h
Chacun de ces modules contient la définition de fonctions appellées par le main.

J'ai besoin de déclarer des variables qui soient visibles par les 3 modules, mais pas par le main.
m1 possède une fonction qui lit un fichier config et initialise les variables.
m2 et m3 les utilise une fois initialisées.

J'ai commencé par créer un fichier var.h, contenant la déclaration des variables :
ex: char toto[30];

Lors de la compilation, j'ai une redéfintition.

J'ai donc ajouté :
#ifndef VARIABLE_H
#define VARIABLE_H
char toto[30];
#endif

Lors de la compilation je n'ai plus de redéfinition, mais j'en ai une lors de l'édition de lien, me disant que la variable est déclarée dans les 3 modules, donc redéfinition.

J'ai donc modifié en :
#ifndef VARIABLE_H
#define VARIABLE_H
static char toto[30];
#endif

Je n'ai plus de redéfinition, pas d'erreur, pas de warning
Main appelle la fonction qui lit le fichier config et initialise correctement les variables.
Lorsque je débug et que je pose un breakpoint juste avant l'accolade de la fin de la fonction readconfig, je vois les variables initialisées.

Lorsque je sors de la fonction, je me retrouve avec mes variables vides.
Pouvez vous m'expliquer ou était mon problême (sachant que je l'ai résolu avec des "extern char" ) ?

5 réponses

Messages postés
65
Date d'inscription
vendredi 10 février 2006
Statut
Membre
Dernière intervention
21 octobre 2009

C'est trés simple.
Les variable global porte sur la partie du code les comprenant donc sur un seul fichier. Pour dire au compilateur que la ressource (ici ta variable toto) est défini dans un autre fichier tu dois ajouter extern devant.
Donc dans ton fichier principal tu as ta déclaration :
char toto[30];
et dans ton .h, tu as
extern char toto[];
voila tout tes fichier incluant ton .h peuvent lire et ecrire sur ta variable.
Le mot clé static est utilisé lorsque tu veux que une fonction ai une ou plusieurs variables qui restent en memoire meme aprés la fin de cette fonction.
Bye
Messages postés
966
Date d'inscription
samedi 3 avril 2004
Statut
Membre
Dernière intervention
4 mars 2010
4
Tout d'abord, les variables static (de tous types et toutes portées) ne sont pas sur la pile pour des raisons évidentes, de même que toutes les variables de portée supérieure à celles déclarées dans une fonction.
Ensuite, quant le mot-clé static est utilisé en portée fichier, cela signifie que la variable ne reçoit pas de linkage, elle est propre au fichier, donc il n'y a pas de problème de redéfinition.
En fait, dans ton cas, il faut te rendre compte que tu as autant de variables que de déclarations, ce qui explique pourquoi, bien que tu en fasses l'initialisation dans une fonction, cela n'apparaît pas quand tu retournes dans l'autre fichier, puisqu'il s'agit d'une variable différente. Je ne sais pas quel IDE tu utilises mais si tu peux visualiser les adresses de tes variables tu verras que ce ne sont pas les mêmes.
Messages postés
966
Date d'inscription
samedi 3 avril 2004
Statut
Membre
Dernière intervention
4 mars 2010
4
oui j'avais compris ta demande.
bon à vrai dire je ne sais pas très bien comment ça marche, il me semble qu'au moment de la compilation les modules sont d'abord compilés séparement, les variables partagées reçoivent un nom global et après le linker remplace les noms sur l'ensemble du code par les adresses mémoires (édition des liens je crois que ça s'appelle). Du coup on ne peut avoir de variables de même nom, car sinon il y a conflit, le linker saura pas laquelle prendre (cas où on ne les déclare pas comme static).
Le fait que la variable ne reçoive pas de linkage (déclarée static donc) signifie que le compilateur ne lui attribue pas de nom global, et n'essaye pas de la partager entre les modules, il l'associe à un module en particulier. Sans doute que l'adresse mémoire est complétée directement dans le code, tout au moins réservée. Donc la variable est valide seulement dans ce contexte là. Après, du coup, tu peux donner le même nom à d'autres variables dans d'autres modules, puisque le nom utilisé n'est pas global, il n'y aura pas de conflit, chaque module utilisera 'sa' variable propre.
Je sais pas si c'est très clair, le point important est qu'une variable static déclarée de la sorte a une portée limitée au module dans lequel elle est déclarée, donc on peut réutiliser le nom dans un autre module puisqu'il ne 'voit' pas la première variable.
Messages postés
223
Date d'inscription
mercredi 31 mai 2006
Statut
Membre
Dernière intervention
5 mai 2014

Une fois que les modules sont compilés et linkés, le code ne sait plus dans quel module étaient écrites les procédures, ni dans quel module étaient déclarées les variables.
Seul l'étage de la pile est connu, et les variables déclarées dans un étage sont vues par tous les étages supérieurs.
Le static permet lorsque la pile descent d'un étage, de ne pas libérer la variable de la mémoire et de la retrouver lorsque la pile remonte.
De plus je n'ai aucune erreur, pas même de warning.

Les variables sont biens vues par chacunes de mes fonctions, mais la sortie de la fonction me fait perdre les données stockées dans les variables alors que la variable existe toujours.

Je suis d'accord avec toi, mais je pense qu'il y a une autre explication à mon pb.

Merci
Messages postés
223
Date d'inscription
mercredi 31 mai 2006
Statut
Membre
Dernière intervention
5 mai 2014

Salut

Je n'ai pas compris ca :
"quant le mot-clé static est utilisé en portée fichier, cela signifie que la variable ne reçoit pas de linkage, elle est propre au fichier"

Et je n'ai pas compris pourquoi dans mon cas, la variable se dédouble.
Si elle se dédoublait, il y aurait redéfinition ?! comment plusieurs variables de même portée peuvent elles posséder le même nom ?

Je précise que je n'essai pas de résoudre mon problême, car j'ai recoder d'une autre manière. Je veux juste essayer de comprendre ce dédoublement.

Merci