Le C a les défauts de sa compacité et de sa souplesse :
C'est un langage pour les programmeurs conscients des limites de l'ordinateur et qui veulent en tirer le maximum des possibilités offerts par le langage.
main()
qui doit être présente dans tous les programmes C.;
ou l'accolade fermée }
.{
et l'accolade fermée }
./* Ceci est un commentaire */
Toute donnée en C appartient à un certain type. toutes les valeurs (constantes et variables) utilisées dans les programmes sont classées selon cette typologie. Dans la déclaration d'une variable, le type indique au compilateur le nombre d'octets à réserver.
Classification des types :
typedef
)En C, il existe trois types de base :
Les types de base correspondent directement aux différents codages des variables en mémoire. Alors, ils posent un éventuel problème de portabilité puisqu'ils peuvent dépendre du matériel (machines à 16 ou 32 bits)
Correspond à la taille naturelle de l'entier manipulé par le microprocesseur, donc à la taille du mot mémoire ou des registres, c'est-à-dire 16, 32 ou 64 bits.
int
→ entier signéunsigned int
→ entier non-signé
Pour préciser explicitement la taille désirée, on utilise des modificateurs : short
et long
.
short int
→ entier signé codé sur 2 octets de -32 768 à 32 767.unsigned short int
→ entier non-signé codé sur 2 octets, 0 à 65 535 (216)long int
→ entier signé codé sur 4 octets de -2 147 483 648 à 2 147 483 647.unsigned long int
→ entier non-signé codé sur 4 octets, 0 à 4 294 967 295 (232)
Le int
est facultatif parce que dès qu'il y a un modificateur long
, short
ou unsigned
, l'identificateur est sous-entendu. De plus, un int
peut être de 2 ou 4 octets. S'il est de 2 octets, il correspond à un short
et s'il est de 4 octets, il correspond à un long
.
Les nombres réels (décimaux) sont stockés en C autrement que les entiers. Les nombres réels sont des nombres à virgule flottante. La virgule en tant que séparateur entre la partie entière et la partie décimale n'est pas figée, contrairement aux nombres à virgule fixe. La grandeur d'un tel nombre est donnée par un exposant adéquat.
Les nombres flottants (réels) sont codés avec une mantisse (les chiffres significatifs) et un exposant.
float
→ flottant codé sur 4 octetsdouble
→ flottant codé sur 8 octetslong double
→ flottant codé sur 10 octetsLe nombre de chiffres significatifs et la valeur de maximum de l'exposant dépendent du codage exact retenu, mais sont pour le codage de type IEEE.
float
→ 7 chiffres significatifs et un exposant de <html>10±38</html>.double
→ 15 chiffres significatifs et un exposant de <html>10±308</html>.long double
→ 15 chiffres significatifs et un exposant de <html>10±4932</html> (norme ANSI).Type | Occupation mémoire | Plage des valeurs |
---|---|---|
float | 4 octets (32bits) | 3.4 * 10-38 à 3.4 * 1038 |
double | 8 octets (32bits) | 1.7 * 10-308 à 1.7 * 10308 |
long double | 10 octets (32bits) | 3.4 * 10-4932 à 3.4 * 104932 |
Le type caractère spécifie une variable pouvant contenir un caractère unique codé par un entier sur un octet.
char
→ Caractère signé de -128 à 127unsigned char
→ Caractère non signé de 0 à 255
Cette valeur numérique entière représente le code ASCII du caractère dans la plupart des cas, ou dans un autre code standard. Si on limite au code ASCII à 128 caractères, les deux déclarations précédentes sont équivalentes. Si on désire utiliser 256 codes possibles, comme dans le cas des caractères graphiques IBM-PC, il faut utiliser le modificateur unsigned
pour ne pas traiter des caractères à valeur négative. Dans une représentation signée, le bit de poids fort est considéré comme le bit de signe.
Le type caractère est véritablement considéré comme ayant une valeur numérique entière, donc on peut l'utiliser directement dans les expressions de calcul.
c = 'a' + rand()%26;
Le type char
correspond à un caractère unique et une chaîne de caractères correspond à un tableau d'éléments de type char
.
L'ensemble constitué par plusieurs instructions entre accolades est appelé un bloc d'instructions (compound statement). Syntaxiquement, un bloc d'instruction compte pour une seule instruction.
L'énoncé if-else sert à contrôler l'exécution d'un programme. Il permet de faire un choix entre deux alternatives. La condition doit être entre parenthèses.
if (<condition>) <énoncé1>; else <énoncé2>;
Si la condition entre parenthèses est vraie, ou si l'expression retourne un résultat non-nul, alors l'énoncé 1 est exécuté et l'exécution de l'énoncé if est terminé.
Si la condition entre parenthèses est fausse, ou si l'expression retourne un résultat nul, alors l'énoncé 2 est exécuté (s'il existe) ou rien n'est exécuté s'il est omis.
if (i>10) i = 0; else { printf("La valeur de i est : %d\n",i); i++; } if (i) instruction; /* est équivalent à if(i!=0) instruction; */ if (!i) instruction; /* est équivalent à if(i==0) instruction; */
if (i=0)
→ Condition invariable, parce que c'est une affectation. La partie alternative else
sera toujours exécutée, peu importe la valeur de la variable i
, parce que i=0
sera interprété comme faux.
La condition du if
peut comporter plusieurs conditions partielles.
if (x>y && x>0) printf("x est plus grand que y et est positif.");
Pour afficher le message, il faut que les deux conditions x>y
et x>0
soient vraies. Sinon, l'évaluation donnerait la valeur 0 (pour false
) et donc le message ne serait pas affiché.
Il n'est pas obligatoire que la condition d'un if
soit :
Étant donné que chaque expression dont la valeur diffère de 0 vaut true
et que chaque expression de valeur nulle vaut false
, on peut utiliser des expressions constantes comme conditions d'instructions if
.
if (5) printf("La condition est vraie."); if (0) printf("La condition est fausse et ce message ne sera pas affiché.");
Pour des choix à plusieurs cas en fonction de conditions successives, on utilise une imbrication des conditions.
if (condition1) instruction1; else if (condition2) instruction2; else if (condition3) instruction3; else instruction4;
Chaque instruction est associée à une condition et le dernier else
, s'il existe, correspond au cas où aucune condition n'est vraie.
Dans une imbrication, un else
se rapporte toujours au if
le plus rapproché. Pour rattacher une branche else à un autre if
que le premier if
précédant et dépourvu de branche else
, il faut utiliser des accolades en créant un ou plusieurs blocs.
if (n>0) if (a>b z=a; else z=b;
Dans l'exemple précédant, malgré le fait que l'indentation est mal faite, le else
n'est pas associé au premier if
, mais bien au if
directement au-dessus. Comme spécifié précédemment, on peut corriger avec les accolades.
if (n>0) { if (a>b) z=a; } else z=b;
Dans le cas précédant, le else
est associé au premier if
.
L'instruction switch
réalise un aiguillage vers différentes instructions en fonction du contenu d'une variable de contrôle.
switch (expression) { case constante_1 : [instruction(s);] case constante_1 : [instruction(s);] . . case constante_n : [instruction(s);] [default : instruction(s);] }
L'expression qui est l'objet du switch
est évaluée, convertie éventuellement en entier, et sa valeur est recherchée successivement parmi les valeurs des diverses expression constantes entières. En cas d'égalité, les instructions correspondantes sont exécutées.
Les crochets ([]
) indiquent que les instructions sont facultatives après une constante case
(les crochets ne font pas partie de l'instruction switch
.
Lorsqu'aucun cas n'est sélectionné, on exécute les instructions correspondant au cas default
s'il existe, la branche default
est facultative.
L'instruction break
fait sortir avant terme du switch
et provoque un saut après la structure switch
. Toutes les instructions éventuelles du switch
placées après l'instruction break
ne seront pas exécutés et le programme se poursuit à l'instruction placée immédiatement après la structure switch
.
Les constantes case
sont des valeurs numériques entières, ou des constantes caractères, représentés dans la machine par des nombres entiers.
Une seule instruction ou un seul groupe d'instruction peut correspondre à plusieurs étiquettes case
. Alors, on écrit les instructions après la dernière des étiquettes case
concernées par les instructions.
case 'a' : case 'A' : printf("\n\nLa somme des nombre est : %f, x+y); break;
Le langage C dispose de plus de 40 opérateurs. Ils ont des critères de classification selon :
?
→ opérateur conditionnel)La priorité des opérateurs est très importante.
Les opérateurs binaires, ou dyadiques, agissent sur deux opérandes. Les opérateurs unaires, ou monadiques, agissent sur un seul opérande.
Les différents opérateurs n'ont pas tous la même priorité.
Niveau | Opérateurs | Sens de priorité |
---|---|---|
1 | ( ) [ ] | Gauche à droite |
2 | ! ~ ++ – | Droite à gauche |
3 | * / % | Gauche à droite |
4 | + - | Gauche à droite |
5 | << >> | Gauche à droite |
6 | < <= > >= | Gauche à droite |
7 | == != | Gauche à droite |
8 | & (et bit) | Gauche à droite |
9 | ^ (ou exclusif) | Gauche à droite |
10 | | (ou bit) | Gauche à droite |
11 | && | Gauche à droite |
12 | || | Gauche à droite |
13 | = += -= | Droite à gauche |
Certains opérateurs se situent au même niveau de priorité, alors l'ordre d'exécution dépend de leur position relative dans l'expression arithmétique. Pour la plupart des niveaux, une opération sera d'abord effectuée si elle se trouve plus à gauche dans l'expression.
Le programmeur peut imposer lui-même une conversion en préfixant l'opération d'un type entre parenthèses. Ainsi, en écrivant x=(float) i/j;
on force le compilateur à effectuer une conversion d'entier à réel sur i
. Alors le dividende est un réel et le résultat est un réel. Le fait d'imposer une conversion porte, en anglais, le nom de casting.
Les opérateurs arithmétiques suivant sont disponibles :
Opérateur | Symbole | Type | Signification |
---|---|---|---|
Addition | + | Binaire | |
Soustraction | - | Binaire | |
Multiplication | * | Binaire | |
Division | / | Binaire | La division entière → 5/3 = 1 |
Modulo | % | Binaire | Le reste de la division → 5%3 = 2 |
Affectation | = | Binaire | |
Incrément | ++ | Unaire | Ajoute 1 à la valeur d'une variable |
Décrément | – | Unaire | Soustrait 1 à la valeur d'une variable |
Plus | + | Unaire | Ajout du standard ANSI |
Moins | - | Unaire | Agit sur l'opérande qui le suit, en changeant le signe |
L'opérateur d'affectation est spécifique à C, car dans d'autres langages, l'affectation n'est pas considérée comme opérateur. Le résultat de cet opérateur est la valeur affectée.
i = 3; /* met 3 dans i et retourne 3 qui pourra être utilisé à d'autres fins */ i=(j=5)+9; /* affecte la valeur 14 à i */
Si l'opérateur précède l'opérande, il modifie tout de suite et la nouvelle valeur est dans le reste de l'expression.
i = --j; /* est équivalent à : j=j-1; i=j; */
Si l'opérateur suit l'opérande, la valeur initiale de l'opérande est utilisée dans l'expression et on modifie la valeur après.
i = j++; /* est équivalent à : i=j; j=j+1; */
Les deux instructions compteur++
et ++compteur
ont le même effets s'ils sont indépendant et ne font pas partie d'une autre expression/instruction.
L'opérateur qui suit (compteur++
) est appelée la post-incrémentation et l'opérateur qui précède (++compteur
) est appelée la pré-incrémentation.
Les opérateurs combinés ne sont pas de nouveaux opérateurs, mais plutôt deux opérateurs qui agissent comme un seul. Combiner l'opérateur d'affectation d'affectation (=
) avec tous les opérateurs binaires permet d'optenir une expression plus concise et accélère l'exécution du programme.
i *= 5; /* équivaut à : i = i * 5; */
La variable à gauche de l'opérateur (dans l'exemple précédent, i
) servira deux fois :
Alors, le compilateur n'a pas à calculer à deux reprises l'emplacement de cette variable en mémoire, donc on accélère l'exécution.
La construction a op=b
signifie a = a op(b)
, donc on doit toujours évaluer l'expression à droite du =
avant de lui appliquer l'opérateur combiné.
Les opérateurs logiques par ordre décroissant de priorité :
Priorité | Symbole | Signification |
---|---|---|
1 | ! | Non (négation) |
2 | > >= < <= | Tests de supériorité et d'infériorité |
3 | == != | Tests d'égalité et d'inégalité |
4 | && || | ET et OU logiques |
L'opérateur de négation (!) inverse une condition.
i > j
est vrai, alors !(i > j)
est faux.i > j
est faux, alors !(i > j)
est vrai.if (i)
est équivalent à if (i != 0)
if (!i)
est équivalent à if (i == 0)
main() { int i,j; printf("Entrez i et j : "); scanf("%d%d", &i, &j); if (i==j) printf("Egalite entre i et j."); if (i!=j) printf("i est different de j."); if (i>j) printf("i est plus grand que j."); if (i>=j) printf("i est plus grand ou egal a j."); if (i>=2 && i<=10) printf("i est entre 2 et 10 inclus."); if ((i>=2)||(i<=10)) printf("Toujours vrai"); }
Il permet de combiner deux valeurs selon la table de vérité ET.
<html><table><tr><td> <table class=“inline”>
<tr class="row0"> <th class="col0" colspan="3"> Table de vérité ET </th>
</tr> <tr class="row1"> <th class="col0 rightalign"> </th><th class="col1"> 0 </th><th class="col2"> 1 </th> </tr> <tr class="row2"> <th class="col0"> 0 </th><td class="col1"> 0 </td><td class="col2"> 0 </td>
</tr> <tr class="row3"> <th class="col0"> 1 </th><td class="col1"> 0 </td><td class="col2"> 1 </td> </tr>
</table> </td><td> </td><td> <table class=“inline”>
<tr class="row0">
<th class="col0" colspan="2"> Exemple </th> </tr> <tr class="row1"> <td class="col0"> </td><td class="col1"> 1 101 011 110 000 101 </td> </tr> <tr class="row2">
<td class="col0"> ET </td><td class="col1"> 0 101 001 100 011 110 </td> </tr> <tr class="row3"> <td class="col0"> Résultat </td><td class="col1"> 0 101 001 100 000 100 </td> </tr>
</table> </td></tr></table></html>
Il permet de combiner deux valeurs selon la table de vérité OU.
<html><table><tr><td> <table class=“inline”>
<tr class="row0"> <th class="col0" colspan="3"> Table de vérité OU </th>
</tr> <tr class="row1"> <th class="col0 rightalign"> </th><th class="col1"> 0 </th><th class="col2"> 1 </th> </tr> <tr class="row2"> <th class="col0"> 0 </th><td class="col1"> 0 </td><td class="col2"> 1 </td>
</tr> <tr class="row3"> <th class="col0"> 1 </th><td class="col1"> 1 </td><td class="col2"> 1 </td> </tr>
</table> </td><td> </td><td> <table class=“inline”>
<tr class="row0">
<th class="col0" colspan="2"> Exemple </th> </tr> <tr class="row1"> <td class="col0"> </td><td class="col1"> 1 101 011 110 000 101 </td> </tr> <tr class="row2">
<td class="col0"> OU </td><td class="col1"> 0 101 001 100 011 110 </td> </tr> <tr class="row3"> <td class="col0"> Résultat </td><td class="col1"> 1 101 011 110 011 111 </td> </tr>
</table> </td></tr></table></html>
Il permet aussi de combiner deux valeurs selon la règle de la table de vérité OU exclusif (XOR).
<html><table><tr><td> <table class=“inline”>
<tr class="row0"> <th class="col0" colspan="3"> Table de vérité XOR </th> </tr> <tr class="row1"> <th class="col0 rightalign"> </th><th class="col1"> 0 </th><th class="col2"> 1 </th> </tr> <tr class="row2"> <th class="col0"> 0 </th><td class="col1"> 0 </td><td class="col2"> 1 </td> </tr> <tr class="row3"> <th class="col0"> 1 </th><td class="col1"> 1 </td><td class="col2"> 0 </td> </tr>
</table> </td><td> </td><td> <table class=“inline”>
<tr class="row0"> <th class="col0" colspan="2"> Exemple </th> </tr> <tr class="row1"> <td class="col0"> </td><td class="col1"> 1 101 011 110 000 101 </td> </tr> <tr class="row2"> <td class="col0"> XOR </td><td class="col1"> 0 101 001 100 011 110 </td> </tr> <tr class="row3"> <td class="col0"> Résultat </td><td class="col1"> 1 000 010 010 011 011 </td> </tr>
</table> </td></tr></table></html>
Lorsqu'on utilise le ou exclusif, pour que le résultat soit 1, il faut que les deux bits soient de valeur différente.
Ce sont des opérations qu'on trouve plutôt dans les langages d'assemblage que dans les langages de haut niveau et qui permettent des manipulation de données au niveau du bit.
Ces opérations ne s'appliquent pas à des float ou des double, ces opérations s'appliquent à des valeurs entières (int, long, char).
Symbole | Signification |
---|---|
& | ET (AND) |
| | OU (OR) |
^ | OU exclusif (XOR) |
<< | Décalage à gauche |
>> | Décalage à droite |
~ | Complément à un |
ET | OU | OU exclusif |
---|---|---|
1&1=1 | 1|1=1 | 1^1=0 |
1&0=0 | 1|0=1 | 1^0=1 |
0&1=0 | 0|1=1 | 1^1=1 |
0&0=0 | 0|0=0 | 1^0=0 |
L'opérateur de traitement de bit &
permet de forcer à 0 des zones binaires particulières à l'intérieur d'une donnée et de tester si tel bit (ou tel groupe de bits) vaut 1. Exemple → compteur = i & 0177
(le 0177
en octal, ou 000001111111
en binaire). Affecter à compteur
les 7 bits les moins significatifs de i
permet d'isoler le code ASCII d'un caractère lu, ou encore, de restreindre à 127 (la valeur décimale de 0177
octal) la valeur à affecter à la variable compteur
.
L'opérateur | sert à forcer à 1 des bits de données. Exemple → i = i|0xFF03;
. Force à 1 les deux bits les moins significatifs et les 8 bits les plus significatifs de i
.
L'opérateur d'adressage &
fournit l'adresse de son opérande qui doit être une Lvalue (une expression désignant une adresse en mémoire, par exemple le nom d'une variable).
&x
donne l'adresse de la variable x
qui est une Lvalue. Sa priorité est de 14, sur une échelle de 15, et 15 étant le plus haut.
Le mécanisme d'indexation est lié à la notion des pointeurs. Pour un tableau mono-indicé a[]
, l'identificateur a
étant une constante de type pointeur sur le début du tableau, l'expression a[i]
représente le i-ème élément suivant l'élément zéro, donc le i+1
ème élément du tableau.
Les opérateurs point (.
) et ->
permettent l'accès aux champs des variables de type structure ou union.
Les structures et les unions sont souvent désignées de façon indirecte par pointeur plutôt que par un identificateur.
struct modele *ptr; i = (*ptr).champ; /* est équivalent à */ i = ptr->champ;
Il existe en langage C un opérateur ternaire (à trois opérandes), semblable au if-else.
<condition> ? <expression1> : <expression2>;
Avec l'opérateur conditionnel, la condition est évaluée en premier. Si la condition est vraie, alors le résultat est la valeur de l'expression 1. Si la condition est fausse, alors le résultat est la valeur de l'expression 2.
int i1, i2, i3; /* on veut faire i3 = max(i1,i2); */ i3 = (i1>i2) ? i1 : i2; /* l'instruction précédente est équivalente à */ if (i1>i2) i3 = i1; else i3 = i2;
La première forme (avec l'opérateur conditionnel) est plus concise puisqu'on n'y mentionne i3
qu'une seule fois.
La syntaxe de l'opérateur d'évaluation séquentielle est la suivante :
<expression1>, <expression2>
Lors de l'exécution de cette opération, la première expression est évaluée et son résultat est ignoré. La seconde expression est évaluée et son résultat devient celui de l'expression au complet. Même si le résultat de la première expression est rejeté, il est important de faire l'évaluation puisqu'elle peut contenir des opérateurs ++
ou –
, ou une affectation modifiant la valeur de la variable.
L'utilisation de cet opérateur est surtout lors des étapes d'initialisation et de réinitialisation d'une boucle for
, pour manipuler plusieurs variables. En effet, une seule expression est permise à ces endroits. Il ne s'agit pas d'énoncés que l'on peut remplacer par un bloc. On se sert donc finalement de l'opérateur d'évaluation séquentielle pour rassembler plusieurs expressions dans une seule.
Chacune des trois expressions d'une boucle for
peut être omise, ce qui est bien car elles ne sont pas toujours nécessaires.
for (somme = 0,i=1; i<10;i++) somme += i; for (somme = 0, i=1; i<=10) somme += i++; for (somme = i = 0; i<10) somme += ++i;
L'opérateur unaire de dimension (taille) sizeof
calcule l'occupation mémoire en octets requise par une variable ou par un type de donnée.
sizeof(<expression>) /* l'expression est un identificateur de variable */ sizeof(<type>) /* le type est un identificateur de type */
L'opérateur retourne une constante entière qui représente la taille mémoire en octets occupée par la variable ou par le type. L'opérateur permet de résoudre, d'une façon portable et indépendante du codage en mémoire, les problèmes liés à la taille des données :
short s; int i; long l; double d; sizeof(s); sizeof(short); /* retourne 2 (octets) */ sizeof(i); sizeof(int); /* retourne 2 ou 4 (octets) selon l'occupation mémoire sur un ordinateur particulier concerné */ sizeof(l); sizeof(long); /* retourne 4 (octets) */ sizeof(d); sizeof(double); /* retourne 8 (octets) */
Les itérations (structures répétitives ou boucles) permettent l'exécution plusieurs fois de certaines parties du programme, sans réécrire les instructions.
Les structures répétitives :
while
⇒ évaluation → exécutionfor
⇒ évaluation → exécutiondo while
⇒ exécution → évaluation
La structure while
permet de faire répéter l'exécution du bloc d'instructions tant qu'une certaine condition est remplie (donc égale à true
).
while (<expression>) instruction;
while (<expression>) { instruction1; instruction2; instructionn; }
int x=10; while (x>0) { printf("%d",x); x--; }
Un while
n'accepte formellement qu'une instruction dépendante, donc pour plusieurs instructions à exécuter, il faut utiliser le bloc d'instructions, afin de tenir compte de cette exigence syntaxique.
int a=-4; while (a!=0) /* tant que a est différent de 0 */ { a++; printf("%d\t", a); } /* boucle sans bloc d'instructions */ while (a!=0) a++; printf("%d\t",a); /* instructions non placée entre accolades, donc ce n'est pas un bloc */
-3 -2 -1 0
Pour le deuxième while
, seulement l'instruction a++;
dépend de la condition de bouclage. L'instruction printf(“%d\t”, a);
sera exécutée une seule fois parce qu'ell ne dépend d'aucune condition. Elle sera exécutée à la sortie de la boucle quand a=0
.
Comme la structure while, la structure for
est une boucle itérative, une instruction répétitive qui teste une condition avant d'exécuter les instructions. Les instructions sont exécutées et répétées tant que la condition de bouclage est remplie (true
). Cet énoncé implante une boucle généralisée dans laquelle tous les éléments de contrôle de la boucle sont rassemblés au même endroit.
Elle comprend trois éléments :
for (initialisation; condition; réinitialisation) instruction(s)
L'énoncé for
effectue les opérations suivantes :
for
est terminée (les étapes 4, 5, 6 ne sont pas exécutés)for (i=1; i<=10; i++) { somme += i; }
La structure for
constitue une alternative syntaxique au while dans laquelle tous les éléments relatifs au contrôle de la boucle (initialisation, condition de bouclage et réinitialisation) sont rassemblés dans l'entête de boucle, ce qui a pour avantage d'être lisible et compacte. On peut toujours écrire une boucle for
à l'aide d'un énoncé while
.
somme = 0; i = 1; /* initialisation */ while (i<=10) /* condition de bouclage */ { somme += i; /* instruction */ i++; /* réinitialisation */ }
La première forme (boucle for
) est plus claire car elle regroupe tous les éléments de contrôle de la boucle. Ceci est encore plus évident lorsque le corps de la boucle contient plusieurs instructions.
Pour définir une fonction en C, il faut coder les instructions qu'elle doit exécuter, en respectant certaines règles syntaxiques. Le code source de la fonction est appelé définition de la fonction. Une définition de fonction doit spécifier :
<classe> <type> <déclarateur/nom> <paramètres>
{ <Définition de variables locales> <Définition de variables externes> <Déclaration de fonctions supplémentaires> ... <Instructions> }
extern
auto
static
register
extern
⇒ Indique qu'il s'agit de la déclaration d'une variable définie dans un autre module. Les variables globales ont la classe extern
lorsqu'elles sont définies sans aucune indication de classe de mémorisation.
int e; /* e a la classe extern */ main () { ... }
auto
⇒ Dans une déclaration interne à un bloc, indique qu'il s'agit d'une variable à durée de vie temporaire avec une visibilité restreinte au bloc (option par défaut).
static
⇒ Implique une durée de vie permanente, mais a une signification différente dépendant de l'emplacement de la déclaration.
auto
.
register
⇒ demande une allocation dans un registre du microprocesseur dans un but d'optimisation du temps d'exécution.