Next: 6 Objets structurés
Up: Le langage C
Previous: 4 Structure de programmes
Les variables ne sont pas les seules entités possédant l'attribut de classification: il en est de même des fonctions (voir chapitre 4).
Toute variable définie à l'extérieur des fonctions est une variable globale. Comme nous l'avons dit (voir section 1.6), les variables globales ne sont pas les seules variables possibles: les variables définies à l'intérieur des fonctions sont des variables locales.
Une variable globale est connue donc utilisable dans n'importe quelle partie du fichier
où elle est définie; en particulier
à l'intérieur de n'importe quelle fonction du
module
.
Cette portée peut même s'étendre à d'autres modules du programme,
si le programme est constitué de plusieurs fichiers
(voir section 5.2.1).
Un bloc est une suite de déclarations suivies par des instructions, le tout encadré par une accolade ouvrante { et une accolade fermante }. Le corps d'une fonction est encadré par des accolades: c'est donc une bloc. Une variable locale est définie à l'intérieur d'une fonction et au début d'un bloc (c'est le seul endroit où il est permis de définir des variables locales). Une variable locale n'est connue qu'à l'intérieur du bloc dans lequel elle est définie.
int g; g est une variable globalemain() { int i; i est une variable locale for (i=1; i<=100; i++) { int j; j est une variable locale for (j=1; j<=100; j++) { g = pcgd(i, j); i, j et g sont accessibles ici printf("Le pgcd de %d et de %d est %d
n", i, j, g); ... } j n'est plus accessible à partir d'ici ... } i n'est plus accessible à partir d'ici }
Il n'y a aucune restriction syntaxique dans le choix des noms de variables globales ou locales; il est donc possible de définir (par inadvertance, le plus souvent) une variable locale et une variable globale ayant le même nom. Le compilateur C ne génèrera pas d'erreur. Dans la portée de la variable locale, c'est la variable locale qui sera choisie; sinon c'est la variable globale. Par exemple, le programme suivant affichera 150 puis 100.
int g = 100; g est une variable globalemain() { if (g==0) { Il s'agit de la variable globale int g = 50; g est une variable locale printf("%d", g); Il s'agit de la variable locale } else printf("%d", g); Il s'agit de la variable globale }
Il en est de même pour une variable globale et un paramètre formel.
int g = 100; g est une variable globalevoid qqchose(int g) { Il s'agit d'un paramètre formel if (g==0) g est le paramètre formel ....
}
Même remarque pour deux variables locales de même nom.
On retiendra de ceci que
main() { int g = 100; g est une variable locale if (g==0) { int g = 50; g est une variable locale printf("%d", g); qui masque la déclaration précédante } else printf("%d", g); Il s'agit de la première variable locale }
Les arguments formels des fonctions se comportent comme des variables locales qui ont la particularité d'être automatiquement initialisés par les arguments effectifs lors de l'activation de la fonction.
L'inérêt des variables locales static est d'interdire des modifications inconsidérées (comme on pourrait le faire sur des variables globales) et de n'autoriser ces modifications qu'à l'intérieur de la fonction ou bloc où elle est définie.
Il faut toutesfois utiliser les variables static avec beaucoup de précaution. En particulier, elles sont mal adaptées aux fonctions récursives.
Le qualifieur register placé devant la définition d'une variable informe que celle-ci joue un rôle critique pour le programme et que l'on attend du compilateur qu'il optimise son utilisation. Les variables register doivent être locales et d'un type élémentaire. Elles sont automatiquement initialisées à 0. L'optimisation de l'utilisation d'une telle variable dépend de l'architecture de la machine; dans beaucoup de cas, elles sont stockées dans des registres de la machine et non pas en mémoire centrale. Le nombre de registres étant limité sur toutes les machines, le compilateur accorde ce traitement spécial aux variables dans l'ordre où elles figurent dans les déclarations.
L'intérêt du qualifieur register est très limité dans la mesure où les compilateurs actuels sont assez sophistiqués pour déterminer (parfois mieux que le programmeur lui-même) les variables qui sont critiques et pour faire les optimisations adéquates.
int strlen(char chaine[]) { register int i=0; while (chaine[i] != 0) i++; return i; }
Ce qualifieur peut et doit être évité avec des compilateurs récents et évolués.
Il est toujours conseillé d'utiliser ce qualifieur chaque fois que cela est possible.
Le qualifieur volatile placé devant la définition d'une variable précise au compilateur que la variable peut être modifée de manière ``mystérieuse'' par des interruptions ou autre fonctions du système. Ce renseignement fait que le compilateur s'interdit des optimisations qu'elle aurait effectuées sans ce qualifieur.
Toutes les variables globales sont publiques c'est-à-dire qu'elles peuvent (moyennant une déclaration spécifique) être utilisées dans les autres modules. On peut interdire cette facilité en donnant à ces variables le qualifieur static. On dit alors qu'il s'agit d'une variable privée.
Le qualifieur static d'une variable locale change la durée de vie de celle-ci. Le qualifieur static d'une variable globale restreint sa visibilité au seul module dans lequel elle est définie.On peut donc avoir un même nom pour deux variables globales privées à condition qu'elles figurent dans deux modules différents: ces deux variables sont alors différentes.
Dans un programme composé de plusieurs modules, il faut à tout prix utiliser ce qualifieur static pour rendre privé toutes les variables qui doivent l'être. Sinon, on risque de partager à tort des variables privés.
Comme nous l'avons déjà dit dans la section 1.6, une définition crée physiquement l'objet correspodant alors qu'une déclarartion se limite à indiquer (pour les besoins de la compilatation) que l'objet existera et sera défini plus loin dans le même module ou dans un autre module.
Le qualifieur extern placé devant la déclaration d'une variable ou d'une fonction informe que celui-ci sera défini plus loin dans le même module ou dans un autre module.
A chaque variable, il ne peut y avoir qu'une seule définition. Par contre, il peut y avoir plusieurs déclarations dans le même module ou dans d'autres modules.
Toutes les fonctions sont publiques c'est-à-dire qu'elles peuvent (moyennant une déclaration spécifique, voir plus loin) être utilisées dans les autres modules. On peut interdire cette facilité en donnant à ces fonctions le status static. On dit alors qu'il s'agit d'une fonction privée.
On peut donc avoir un même nom pour deux fonctions privées à condition qu'elles figurent dans deux modules différents. Ceci permet, en particulier, de developper des programmes à plusieurs: il suffit de s'entendre sur les noms des seules fonctions publiques et le choix de noms des fonctions privées peut être laissé aux multiples programmeurs du programme, en étant assuré qu'il n'y aura pas de collision de noms.
Dans un programme composé de modules, il faut à tout prix utiliser ce qualifieur static pour rendre privées toutes les fonctions qui doivent l'être.
Comme nous l'avons déjà dit dans la section 1.6, une défintion crée physiquement l'objet correspodant alors qu'une déclarartion se limite à indiquer (pour les besoins de la compilation) que l'objet existera et sera défini plus loin dans le même module ou dans un autre module.
Le qualifieur extern placé devant la déclaration d'une fonction informe que celle-ci sera définie plus loin dans le même module ou dans un autre module.
A chaque fonction, il ne peut y avoir qu'une seule définition. Par contre, il peut y avoir plusieurs déclarations dans le même module ou dans d'autres modules.
Touraivane