« Programmation C/Classe de stockage » : différence entre les versions

Contenu supprimé Contenu ajouté
Alveric (discussion | contributions)
Séparation en "qualificateurs" et "classes de stockage"
Ligne 1 :
{{Programmation C}}
 
Il est possible de construire des types dérivés des types de base du langage en utilisant plusieurs combinaisons, deux étant illustrées dans ce chapitre: les classes de stockage et les qualificateurs.
 
==Classe de stockage==
 
Le langage C permet de spécifier, avant le type d'une variable, un certain nombre de classe de stockage :
* <code>constauto</code> : pourvaleur définirpar une variable dont la valeurdéfaut, nemot devraitclé jamaisobsolète changer.;
* <code>register</code> : demande au compilateur de faire tout son possible pour utiliser un registre processeur pour cette variable. ;
* <code>auto</code> : valeur par défaut, mot clé obsolète.
* <code>static</code> : rend une définition de variable persistante. ;
* <code>volatile</code> : le contraire de <code>register</code> : une variable pouvant être modifiée notamment par une source externe indépendante du programme.
* <code>register</code> : demande au compilateur de faire tout son possible pour utiliser un registre processeur pour cette variable.
* <code>static</code> : rend une définition de variable persistante.
* <code>extern</code> : déclare une variable sans la définir.
 
Une variable, ou un paramètre de fonction, ne peut avoir qu'au plus une classe de stockage.
===Classe 'const'===
 
===Classe 'constauto'===
Cette classe ne sert qu'à maintenir une certaine compatibilité avec le prédécesseur du C : le langage B. Car en fait, ce dernier ne comportait aucune notion de type, mais uniquement de classe. Comme il fallait bien mettre un mot clé avant la définition d'une variable, celui-ci servait de passe-partout. En C, ce mot clé est tombé en désuétude.
 
===Classe 'register'===
Indique que la variable devrait être stockée dans un registre du processeur. Les registres du processeur sont forcément limités, aussi bien en nombre qu'en taille. Inutile de déclarer une structure entière ou un tableau avec le mot clé <code>register</code>.
 
Qui plus est, les variables registres sont forcément locales à des fonctions. On ne peut pas définir une variable globale en tant que registre.
 
Ce mot-clé est déconseillé sauf pour des cas particuliers, les compilateurs modernes sachant généralement mieux que le programmeur comment optimiser et quelles variables placer dans les registres.
 
<pre>
int main() {
register short i,j;
for (i=1;i<1000;++i)
for(j=1;j<1000;++j)
printf("\n %d %d",i,j)
</pre>
 
===Classe 'static'===
L'effet de la classe 'static' dépend de l'endroit où l'objet est déclaré :
* ''Objet local à une fonction'' : la valeur de la variable sera persistante entre les différents appels de la fonction. C'est une sorte de variable globale privée. L'intérêt de déclarer la variable à l'intérieur de la fonction est de garantir une certaine encapsulation, afin d'éviter des « optimisations » (usages multiples) d'une variable globale. Qui plus est, cela permet d'avoir plusieurs fois le même nom, dans des fonctions différentes.
* ''Objet global'' : comme une variable globale est déjà persistante, le mot-clé <code>static</code> aura pour effet de limiter la visibilité de la variable au seul module où elle est déclarée (cela s'applique aussi et surtout aux fonctions), toujours dans le but de garantir un certain niveau d'encapsulation.
 
Les paramètres des fonctions ne peuvent être déclarés 'static'.
 
===Classe 'extern'===
 
<code>extern</code> permet de déclarer une variable sans la définir. C'est utile lorsqu'elle est définie dans un autre fichier. Toutes variables globales, autres que celles déclarées <code>static</code>, sont accessibles avec ce mot-clé.
 
À noter que le 'extern' est implicite lorsqu'on déclare ou donne le prototype d'une fonction, pas la peine de le rajouter.
 
== Qualificateurs ==
 
Le C définit trois qualificateurs pouvant influer sur une variable :
* <code>const</code> : pour définir une variable dont la valeur ne devrait jamais changer ;
* <code>restrict</code> : permet une optimisation pour la gestion des pointeurs ;
* <code>volatile</code> : le contraire de <code>register</code> :désigne une variable pouvant être modifiée notamment par une source externe indépendante du programme.
 
Une variable, ou un paramètre de fonction, peut avoir aucun, un, deux, ou les trois qualificateurs (certaines combinaisons n'auraient que peu de sens, mais sont autorisées).
 
===Qualifitateur 'const'===
La classe <code>const</code> ne déclare pas une vraie constante, mais indique au compilateur que la valeur de la variable ne doit pas changer. Il est donc impératif d'assigner une valeur à la déclaration de la variable, sans quoi toute tentative de modification ultérieure entrainera une erreur de la part du compilateur :
 
Ligne 47 ⟶ 90 :
Cette dernière forme est néanmoins rarement usitée. En outre ce dernier exemple présente un autre problème qui est la modification d'une chaine de caractères « en dur », qui sont la plupart du temps placées dans la section lecture seule du programme et donc inaltérables.
 
===ClasseQualifitateur 'volatile'===
IlCe mot-clé sert à spécifier au compilateur que la variable peut être modifiée à son insu. ElleCela n'estannule pastoute enregistréeoptimisation dans un registre,que le processeurcompilateur vapourrait doncfaire, laet chercherl'oblige enà mémoireprocéder à chaque utilisationlecture ceou quiécriture baissedans lesune telle variable tel que le programmeur l'a écrit dans le performancescode. Ceci sert par exemple pour les coordonnées d'un pointeur de souris qui seraient modifiées par un autre programme, ou par exemple pour de la programmation avec de multiples fils d'exécution qui doivent communiquer entre eux, ou pour désigner des registres matériels qui peuvent être accédés depuis un programme C (une horloge, par exemple), mais dont la valeur peut changer indépendemment du programme.
Ce mot-clé est l'antonyme de <code>register</code>. Il est peu utilisé.
 
On peut combiner <code>const</code> et <code>volatile</code> dans certaines situations. La norme C donne cet exemple :
Il sert à spécifier au compilateur que la variable peut être modifiée à son insu. Elle n'est pas enregistrée dans un registre, le processeur va donc la chercher en mémoire à chaque utilisation ce qui baisse les performances. Ceci sert par exemple pour les coordonnées d'un pointeur de souris qui seraient modifiées par un autre programme, ou par exemple pour de la programmation avec de multiples fils d'exécution qui doivent communiquer entre eux.
<pre>extern const volatile int horloge_temps_reel;</pre>
qui déclare une variable entière qu'on ne peut modifier à patir du programme, mais dont la valeur peut changer quand même. Elle pourrait désigner une valeur incrémentée régulièrement par une horloge interne.
 
Remarque : Dans le cas d'architectures avec cache non-cohérent le mot-clé <code>volatile</code> oblige le compilateur à lire la variable dans le cache mais pas dans la mémoire.
 
===Classe 'auto'===
Cette classe ne sert qu'à maintenir une certaine compatibilité avec le prédécesseur du C : le langage B. Car en fait, ce dernier ne comportait aucune notion de type, mais uniquement de classe. Comme il fallait bien mettre un mot clé avant la définition d'une variable, celui-ci servait de passe-partout. En C, ce mot clé est tombé en désuétude.
 
===Classe 'register'===
Indique que la variable devrait être stockée dans un registre du processeur. Les registres du processeur sont forcément limités, aussi bien en nombre qu'en taille. Inutile de déclarer une structure entière ou un tableau avec le mot clé <code>register</code>.
 
Qui plus est, les variables registres sont forcément locales à des fonctions. On ne peut pas définir une variable globale en tant que registre.
 
Ce mot-clé est déconseillé sauf pour des cas particuliers, les compilateurs modernes sachant généralement mieux que le programmeur comment optimiser et quelles variables placer dans les registres.
 
<pre>
int main() {
register short i,j;
for (i=1;i<1000;++i)
for(j=1;j<1000;++j)
printf("\n %d %d",i,j)
</pre>
 
===Classe 'static'===
L'effet de la classe 'static' dépend de l'endroit où l'objet est déclaré :
* ''Objet local à une fonction'' : la valeur de la variable sera persistante entre les différents appels de la fonction. C'est une sorte de variable globale privée. L'intérêt de déclarer la variable à l'intérieur de la fonction est de garantir une certaine encapsulation, afin d'éviter des « optimisations » (usages multiples) d'une variable globale. Qui plus est, cela permet d'avoir plusieurs fois le même nom, dans des fonctions différentes.
* ''Objet global'' : comme une variable globale est déjà persistante, le mot-clé <code>static</code> aura pour effet de limiter la visibilité de la variable au seul module où elle est déclarée (cela s'applique aussi et surtout aux fonctions), toujours dans le but de garantir un certain niveau d'encapsulation.
 
Les paramètres des fonctions ne peuvent être déclarés 'static'.
 
===Classe 'extern'===
 
<code>extern</code> permet de déclarer une variable sans la définir. C'est utile lorsqu'elle est définie dans un autre fichier. Toutes variables globales, autres que celles déclarées <code>static</code>, sont accessibles avec ce mot-clé.
 
À noter que le 'extern' est implicite lorsqu'on déclare ou donne le prototype d'une fonction, pas la peine de le rajouter.