Programmation C source/Classe de stockage

int main(void)
 printf("------------------------------\n");
 printf(" Classe de stockage\n");
 printf("------------------------------\n");
 /* auto : pour les variables locales, obsolète
 extern : déclare une variable sans la définir
 register : demande au compilateur de faire tout son possible
 pour utiliser un registre processeur pour cette variable
 static : rend une définition de variable persistante. */
 /* Une variable, ou un paramètre de fonction,
 ne peut avoir qu'au plus une classe de stockage */
 printf("\n------------------------------\n");
 printf(" Classe static\n");
 printf("------------------------------\n");
 void f(void)
 static int i = 0;
 /* i est de type static int
 i ne sera initialisé à 0 qu'au premier appel de f */
 int j = 0;
 /* j est une variable standard
 j sera initialisé à 0 chaque fois */
 i++;
 j++;
 printf("i vaut %d et j vaut %d.\n", i, j);
 f();
 f();
 f();
 /* Objet local à une fonction :
 la valeur de la variable sera persistante entre les différents appels
 de la fonction. La variable ne sera visible que dans la fonction,
 mais ne sera pas réinitialisée à chaque appel de la fonction. */
 /* Objet global et fonction :
 comme une variable globale est déjà persistante,
 le mot-clé static aura pour effet de limiter la visibilité de la variable
 ou de la fonction au seul fichier où elle est déclarée */
 printf("\n------------------------------\n");
 printf(" Classe extern\n");
 printf("------------------------------\n");
 #if 0
 /* extern permet de déclarer une variable sans la définir.
 la variable provient d'un autre fichier.
 exemple */
 // fichier1.c
 int ma_variable_globale_externe;
 // fichier2.c
 extern int ma_variable_globale_externe;
 // permet d'utiliser la variable de fichier1 dans fichier2
 #endif
 printf("\n------------------------------\n");
 printf(" Classe register\n");
 printf("------------------------------\n");
 /* Indique que la variable devrait être stockée dans un registre du processeur
 Cela permet de gagner en performance par rapport à des variables stockées
 en mémoire vive.
 Mais attention les registres du processeur sont limités, aussi bien en nombre
 qu'en taille. Inutile de déclarer une structure entière ou un tableau avec
 le mot clé register.
 les variables placées dans des 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. */
 register short i, j;
 for (i = 1; i < 3; ++i)
 for(j = 1; j < 3; ++j)
 printf("%d %d\n", i, j);
 printf("\n------------------------------\n");
 printf(" Classe auto\n");
 printf("------------------------------\n");
 /* Cette classe est un héritage du langage B.
 Ce mot-clé sert pour les variables locales à une fonction non-statiques.
 Mais une variable déclarée localement à une fonction sans qualificateur static
 étant implicitement automatique, ce mot-clé est inutile */
 printf("\n------------------------------\n");
 printf(" Qualificateurs\n");
 printf("------------------------------\n");
 /* const : pour définir une variable dont la valeur ne devrait jamais changer
 restrict : permet une optimisation pour la gestion des pointeurs
 volatile : 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) */
 printf("\n------------------------------\n");
 printf(" Qualificateur const\n");
 printf("------------------------------\n");
 /* La classe const 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 */
 #if 0
 const int i = 0;
 i = 1; // erreur
 /* Qu'est ce qu'un pointeur ?
 Un pointeur a pour valeur l'adresse d'un objet C d'un type donné */
 int i;
 // la variable i en mémoire a une adresse
 int * p = &i;
 /* p a pour valeur l'adresse de i
 on dit que p pointe sur i de type int */
 // const indique ici qu'on ne modifie pas l'objet pointé
 void fonction(const char * pointeur)
 /* si pointeur = "une chaine de caractères"
 pointeur[0] représente u le premier caractère */
 pointeur[0] = 0; // erreur
 pointeur = "Nouvelle chaine de caractères";
 // const indique ici que la valeur(une adresse) elle-même du pointeur est constante
 char * const pointeur = "Salut tout le monde !";
 pointeur = "Hello world !"; // erreur
 /* les deux à la fois
 indique qu'on ne modifie pas l'objet pointé
 et indique que la valeur(une adresse) elle-même du pointeur est constante */
 const char * const pointeur = "Salut tout le monde !";
 pointeur = "Hello world !"; // erreur
 pointeur[0] = 0; // erreur
 #endif
 printf("\n------------------------------\n");
 printf(" Qualificateur volatile\n");
 printf("------------------------------\n");
 /* Ce mot-clé sert à spécifier au compilateur que la variable peut être modifiée à
 son insu. Cela annule toute optimisation que le compilateur pourrait faire, et
 l'oblige à procéder à chaque lecture ou écriture dans une telle variable tel que
 le programmeur l'a écrit dans le code.
 Ceci a de multiples utilisations :
 pour les coordonnées d'un pointeur de souris qui seraient modifiées par un autre
 programme ;
 pour la gestion des signaux (voir Gestion des signaux) ;
 pour de la programmation avec de multiples fils d'exécution qui doivent
 communiquer entre eux ;
 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épendamment du programme ; */
 #if 0
 // On peut combiner const et volatile dans certaines situations. Par exemple :
 extern const volatile int horloge_temps_reel;
 /* déclare une variable entière, qu'on ne peut modifier à partir du programme,
 mais dont la valeur peut changer quand même, et qui provient d'un autre fichier.
 Elle pourrait désigner une valeur incrémentée régulièrement par une horloge
 interne. */
 #endif
 printf("\n------------------------------\n");
 printf(" Qualificateur restrict\n");
 printf("------------------------------\n");
 /* Introduit par C99, ce mot-clé s'applique aux déclarations de pointeurs
 uniquement. Avec restrict, le programmeur certifie au compilateur que le pointeur
 déclaré sera le seul à pointer sur une zone mémoire. Cela permettra au
 compilateur d'effectuer des optimisations qu'il n'aurait pas pu deviner
 autrement. Le programmeur ne doit pas mentir sous peine de problèmes...
 Par exemple : */
 int * restrict pZone;
 // cc -std=c99 -Wall 3classe.c -o 3classe
 return 0;