INTRODUCTION AU LANGAGE C

char rahc [ ] = "\n/" , redivider [ ] = "Able was I ere I saw elbA" , * deliver,reviled = 1+1 , niam ; main ( ) {/*\} \*/ int tni = 0x0 , rahctup,putchar ( ) ,LACEDx0 = 0xDECAL, rof ; for (;(int) (tni);) (int) (tni) = reviled ; deliver = redivider ; for ((int)(tni)++,++reviled;reviled* *deliver;deliver++,++(int)(tni)) rof = (int) -1- (tni) ;reviled--;--deliver; (tni) = (int) - 0xDECAL + LACEDx0 rof ; for (reviled--,(int)--(tni);(int) (tni);(int)--(tni),--deliver) rahctup = putchar (reviled* *deliver) ; rahctup * putchar ((char) * (rahc)) ; /*\ {\*/}

C
Bernard Cassagne

Bernard Cassagne

Introduction au langage C
norme iso ansi

Laboratoire clips Universit Joseph Fourier & cnrs e Grenoble

Copyright 1997-1998 Bernard Cassagne Ce texte est copyright et n'est pas dans le domaine public. Sa reproduction est cependant e autoris e a condition de respecter les conditions suivantes : e Si ce document est reproduit pour les besoins personnels du reproducteur, toute forme de reproduction totale ou partielle est autoris e. e Si ce document est reproduit dans le but d'^tre distribu de tierces personnes : e ea il devra ^tre reproduit dans son int gralit sans aucune modi cation. Cette e e e notice de copyright devra donc ^tre pr sente. e e il ne devra pas ^tre vendu. Cependant, dans le seul cas d'un enseignement e gratuit, une participation aux frais de reproduction pourra ^tre demand e, mais e e elle ne pourra ^tre sup rieure au prix du papier et de l'encre composant le e e document. Toute reproduction sortant du cadre pr cis ci-dessus est interdite sans accord pr alable e e e de l'auteur. Un chier PostScript contenant ce document est librement accessible par l'url :
ftp: ftp.imag.fr pub DOC.UNIX C Introduction ANSI C.ps

Version de ce document : 2.1 de juin 1998

Table des mati res e
1 Les bases
1.1 1.2 1.3 1.4 1.5 Les versions du langage C . . . . . . . . . . . . Langage et biblioth que standard . . . . . . . . e Les phases de compilation . . . . . . . . . . . . Les jeux de caract res . . . . . . . . . . . . . . e Les unit s lexicales . . . . . . . . . . . . . . . . e 1.5.1 Les mots-cl s . . . . . . . . . . . . . . . e 1.5.2 Les identi cateurs . . . . . . . . . . . . Les commentaires . . . . . . . . . . . . . . . . . Les types de base . . . . . . . . . . . . . . . . . 1.7.1 Les caract res . . . . . . . . . . . . . . . e 1.7.2 Les entiers . . . . . . . . . . . . . . . . 1.7.3 Les ottants . . . . . . . . . . . . . . . . Les constantes . . . . . . . . . . . . . . . . . . 1.8.1 Les constantes enti res . . . . . . . . . . e 1.8.2 Les constantes caract res . . . . . . . . e 1.8.3 Les constantes ottantes . . . . . . . . . Les cha^nes de caract res litt rales . . . . . . .
e e Les constantes nomm es . . . . . . . . . . . . . e 1.10.1 Les de ne . . . . . . . . . . . . . . . . 1.10.2 Les num rations . . . . . . . . . . . . . e e D clarations de variables ayant un type de base e Les op rateurs les plus usuels . . . . . . . . . . e 1.12.1 L'a ectation . . . . . . . . . . . . . . . 1.12.2 L'addition . . . . . . . . . . . . . . . . . 1.12.3 La soustraction . . . . . . . . . . . . . . 1.12.4 La multiplication . . . . . . . . . . . . . 1.12.5 La division . . . . . . . . . . . . . . . . 1.12.6 L'op rateur modulo . . . . . . . . . . . e 1.12.7 Les op rateurs de comparaison . . . . . e Les instructions les plus usuelles . . . . . . . . 1.13.1 Instruction expression . . . . . . . . . . 1.13.2 Instruction compos e . . . . . . . . . . . e 1.13.3 Instruction if . . . . . . . . . . . . . . . Inclusion de source . . . . . . . . . . . . . . . . Les proc dures et les fonctions . . . . . . . . . e iii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 5 6 6 6 7 7 7 10 10 10 10 11 11 11 13 14 14 15 15 16 16 16 17 17 18 18 18 19 19 19 20 20 21 22

5

1.6 1.7 1.8 1.9 1.10 1.11 1.12

1.13 1.14 1.15

1.16 1.17 1.18 1.19 1.20 1.21

1.15.1 D nition d'une fonction . . . . . . . . . . . . . . . . . . . e 1.15.2 Appel d'une fonction . . . . . . . . . . . . . . . . . . . . . . 1.15.3 Les proc dures . . . . . . . . . . . . . . . . . . . . . . . . . e 1.15.4 Fonctions imbriqu es . . . . . . . . . . . . . . . . . . . . . . e 1.15.5 R cursivit . . . . . . . . . . . . . . . . . . . . . . . . . . . e e 1.15.6 R f rence une fonction externe . . . . . . . . . . . . . . . ee a 1.15.7 Comprendre la documentation de la biblioth que standard . e 1.15.8 Les fonctions dans le style K&R . . . . . . . . . . . . . . . Impression formatt e . . . . . . . . . . . . . . . . . . . . . . . . . . e Structure d'un programme . . . . . . . . . . . . . . . . . . . . . . . Terminaison d'un programme . . . . . . . . . . . . . . . . . . . . . Mise en oeuvre du compilateur C sous UNIX . . . . . . . . . . . . Exercice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . R cr ation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e e

. . . . . . . . . . . . . .

. . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

22 24 25 25 25 26 26 26 27 28 29 29 29 33

2 Les tableaux

2.1 Les tableaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.1 D claration de tableaux dont les l ments ont un type de base e ee 2.1.2 Initialisation d'un tableau . . . . . . . . . . . . . . . . . . . . . 2.1.3 R f rence un l ment d'un tableau . . . . . . . . . . . . . . . ee a ee 2.1.4 Cha^nes et tableaux de caract res . . . . . . . . . . . . . . . . .
e 2.2 Les instructions it ratives . . . . . . . . . . . . . . . . . . . . . . . . . e 2.2.1 Instruction for . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.2 Instruction while . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.3 Instruction do . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.4 Instruction break . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.5 Instruction continue . . . . . . . . . . . . . . . . . . . . . . . 2.3 Les op rateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e 2.3.1 Op rateur pr et postincr ment . . . . . . . . . . . . . . . . . . e e e 2.3.2 Op rateur pr et postd cr ment . . . . . . . . . . . . . . . . . e e e e 2.3.3 Quelques utilisations typiques de ces op rateurs . . . . . . . . . e 2.3.4 Op rateur et logique . . . . . . . . . . . . . . . . . . . . . . . . e 2.3.5 Op rateur ou logique . . . . . . . . . . . . . . . . . . . . . . . . e 2.3.6 Op rateur non logique . . . . . . . . . . . . . . . . . . . . . . . e 2.4 Exercice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

35

35 35 36 37 37 37 37 38 39 39 40 40 40 41 41 42 42 43 43

3 Les pointeurs
3.1 3.2 3.3 3.4 3.5 3.6 3.7

Notion de pointeur . . . . . . . . . . . . . . . . . . . . . . . . . . D clarations de variables de type pointeur vers les types de base e Type de pointeur g n rique . . . . . . . . . . . . . . . . . . . . . ee Op rateur adresse de . . . . . . . . . . . . . . . . . . . . . . . . . e Op rateur d'indirection . . . . . . . . . . . . . . . . . . . . . . . e Exercice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pointeurs et op rateurs additifs . . . . . . . . . . . . . . . . . . . e 3.7.1 Op rateurs + et - . . . . . . . . . . . . . . . . . . . . . . . e 3.7.2 Op rateurs ++ et -- . . . . . . . . . . . . . . . . . . . . . e 3.8 Di rence de deux pointeurs . . . . . . . . . . . . . . . . . . . . . e iv

45

45 45 45 46 46 47 49 49 49 50

3.9 Exercice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.10 Passage de param tres . . . . . . . . . . . . . . . . . . . . . . . . . . . e 3.10.1 Les besoins du programmeur . . . . . . . . . . . . . . . . . . . 3.10.2 Comment les langages de programmation satisfont ces besoins . 3.10.3 La strat gie du langage C . . . . . . . . . . . . . . . . . . . . . e 3.11 Discussion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.12 Une derni re pr cision . . . . . . . . . . . . . . . . . . . . . . . . . . . e e 3.13 Exercice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.14 Lecture formatt e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e 3.15 Les derni res instructions . . . . . . . . . . . . . . . . . . . . . . . . . e 3.15.1 Instruction switch . . . . . . . . . . . . . . . . . . . . . . . . . 3.15.2 Instruction goto . . . . . . . . . . . . . . . . . . . . . . . . . . 3.15.3 Instruction nulle . . . . . . . . . . . . . . . . . . . . . . . . . . 3.16 Exercice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.17 R cr ation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e e

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

50 52 52 52 52 53 53 54 56 56 57 59 59 60 63

4 Relations entre tableaux et pointeurs
4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9

4.10 4.11 4.12 4.13 4.14

Conversion des tableaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . L'op rateur d'indexation . . . . . . . . . . . . . . . . . . . . . . . . . . . . e Passage de tableau en param tre . . . . . . . . . . . . . . . . . . . . . . . e Modi cation des l ments d'un tableau pass en param tre . . . . . . . . ee e e Interdiction de modi cation des l ments d'un tableau pass en param tre ee e e Conversion des cha^nes litt rales . . . . . . . . . . . . . . . . . . . . . . .
e Retour sur printf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tableaux multidimensionnels . . . . . . . . . . . . . . . . . . . . . . . . . 4.9.1 D clarations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e 4.9.2 Acc s aux l ments . . . . . . . . . . . . . . . . . . . . . . . . . . . e ee 4.9.3 Passage en param tre . . . . . . . . . . . . . . . . . . . . . . . . . e Initialisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Tableau de pointeurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.12.1 Cas g n ral . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ee 4.12.2 Tableaux de pointeurs vers des cha^nes . . . . . . . . . . . . . . . .
4.12.3 Param tres d'un programme . . . . . . . . . . . . . . . . . . . . . e Tableau et pointeur, c'est la m^me chose? . . . . . . . . . . . . . . . . . . e 4.13.1 Commentaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.13.2 Cas particulier des cha^nes litt rales . . . . . . . . . . . . . . . . .
e R cr ation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

65

65 66 67 68 69 69 70 70 72 72 72 72 73 73 75 75 76 77 78 78 78 79

5 Les entr es-sorties e

5.1 Pointeur invalide . . . . . . . . . . . . . . . 5.2 Ouverture et fermeture de chiers . . . . . . 5.2.1 Ouverture d'un chier : fopen . . . . 5.2.2 fermeture d'un chier : fclose . . . 5.3 Lecture et criture par caract re sur chier e e 5.3.1 lecture par caract re : fgetc . . . . . e v

81

81 81 81 83 84 84

5.4

5.5

5.6 5.7 5.8

5.3.2 lecture par caract re : getc . . . . . . . . . . . e 5.3.3 lecture par caract re : getchar . . . . . . . . . e 5.3.4 criture par caract re : fputc . . . . . . . . . . e e 5.3.5 criture par caract re : putc . . . . . . . . . . . e e 5.3.6 criture par caract re : putchar . . . . . . . . . e e Lecture et criture par lignes sur chier . . . . . . . . e 5.4.1 lecture par ligne : fgets . . . . . . . . . . . . . 5.4.2 lecture par ligne : gets . . . . . . . . . . . . . . 5.4.3 criture par cha^ne : fputs . . . . . . . . . . . . e
5.4.4 criture par cha^ne : puts . . . . . . . . . . . . e
E S formatt es sur chiers . . . . . . . . . . . . . . . . e 5.5.1 Ecriture formatt e : fprintf . . . . . . . . . . e 5.5.2 Ecriture formatt e : printf . . . . . . . . . . . e criture formatt e dans une cha^ne : sprintf . 5.5.3 E e
5.5.4 Exemples d'utilisation des formats . . . . . . . 5.5.5 Entr es formatt es : fscanf . . . . . . . . . . . e e 5.5.6 Entr es formatt es : scanf . . . . . . . . . . . . e e 5.5.7 Entr es formatt es depuis une cha^ne : sscanf . e e
R cr ation . . . . . . . . . . . . . . . . . . . . . . . . . e e Exercice 1 . . . . . . . . . . . . . . . . . . . . . . . . . Exercice 2 . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . .

. 84 . 85 . 85 . 86 . 86 . 86 . 86 . 87 . 87 . 88 . 89 . 89 . 92 . 93 . 94 . 94 . 99 . 99 . 100 . 100 . 100 . 103 . 103 . 105 . 105 . 105 . 105 . 105 . 105 . 107 . 107 . 107 . 108 . 109 . 109 . 109 . 109 . 110 . 110 . 114 . 114 . 115 . 115 . 116 . 116

6 Structures, unions et num rations e e

6.1 Notion de structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2 D claration de structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . e 6.3 Op rateurs sur les structures . . . . . . . . . . . . . . . . . . . . . . . . . e 6.3.1 Acc s aux membres des structures . . . . . . . . . . . . . . . . . . e 6.3.2 A ectation de structures . . . . . . . . . . . . . . . . . . . . . . . . 6.3.3 Comparaison de structures . . . . . . . . . . . . . . . . . . . . . . 6.4 Tableaux de structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.5 Exercice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.6 Pointeurs vers une structure . . . . . . . . . . . . . . . . . . . . . . . . . . 6.7 Structures dont un des membres pointe vers une structure du m^me type e 6.8 Acc s aux l ments d'une structure point e . . . . . . . . . . . . . . . . . e ee e 6.9 Passage de structures en param tre . . . . . . . . . . . . . . . . . . . . . . e 6.10 D termination de la taille allou e a un type . . . . . . . . . . . . . . . . . e e 6.10.1 Retour sur la conversion des tableaux . . . . . . . . . . . . . . . . 6.11 Allocation et lib ration d'espace pour les structures . . . . . . . . . . . . . e 6.11.1 Allocation d'espace : fonctions malloc et calloc . . . . . . . . . . 6.11.2 Lib ration d'espace : proc dure free . . . . . . . . . . . . . . . . . . e e 6.12 Exercice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.13 Les champs de bits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.13.1 G n ralit s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ee e 6.13.2 Contraintes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.14 Les num rations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e e 6.15 Les unions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.16 Acc s aux membres de l'union . . . . . . . . . . . . . . . . . . . . . . . . . e vi

103

6.17 Utilisation pratique des unions . . . . . . . . . . . . . . . . . . . . . . . . . 116 6.18 Une m thode pour all ger l'acc s aux membres . . . . . . . . . . . . . . . . 117 e e e

7 Les expressions

7.1 Les conversions de types . . . . . . . . . . . . . . 7.1.1 Utilit des conversions . . . . . . . . . . . e 7.1.2 Ce qu'il y a dans une conversion . . . . . 7.1.3 L'ensemble des conversions possibles . . . 7.1.4 Les situations de conversions . . . . . . . 7.1.5 La promotion des entiers . . . . . . . . . 7.1.6 Les conversions arithm tiques habituelles e 7.1.7 Les surprises des conversions . . . . . . . 7.2 Les op rateurs . . . . . . . . . . . . . . . . . . . e 7.2.1 Op rateur non bit bit . . . . . . . . . . e a 7.2.2 Op rateur et bit bit . . . . . . . . . . . e a 7.2.3 Op rateur ou bit bit . . . . . . . . . . . e a 7.2.4 Op rateur ou exclusif bit bit . . . . . . . e a 7.2.5 Op rateur d calage gauche . . . . . . . e e a 7.2.6 Op rateur d calage droite . . . . . . . . e e a 7.2.7 Op rateur conditionnel . . . . . . . . . . e 7.2.8 Op rateur virgule . . . . . . . . . . . . . . e 7.2.9 Op rateurs d'a ectation compos e . . . . e e 7.3 Op rateur conversion . . . . . . . . . . . . . . . . e 7.4 S mantique des expressions . . . . . . . . . . . . e 7.4.1 Op rateurs d'adressage . . . . . . . . . . e 7.4.2 Priorit et associativit des op rateurs . . e e e 7.4.3 Ordre d' valuation des op randes . . . . . e e 7.5 R cr ation . . . . . . . . . . . . . . . . . . . . . . e e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. 119 . 119 . 120 . 120 . 121 . 121 . 122 . 123 . 124 . 124 . 125 . 125 . 125 . 125 . 125 . 126 . 126 . 127 . 127 . 129 . 129 . 129 . 131 . 131 . 133 . 133 . 135 . 135 . 137 . 138 . 139 . 139 . 140 . 140 . 140 . 140 . 141

119

8 Le pr processeur e

8.1 Traitement de macros . . . . . . . . . . 8.1.1 Les macros sans param tres . . . e 8.1.2 Macros pr d nies . . . . . . . . ee 8.1.3 Les macros avec param tres . . . e 8.1.4 Les pi ges des macros . . . . . . e 8.1.5 Macros g n rant des instructions ee 8.2 Compilation conditionnelle . . . . . . . 8.2.1 Commande if . . . . . . . . . . 8.2.2 Commandes ifdef et ifndef . 8.2.3 L'op rateur defined . . . . . . . e 8.2.4 La commande error . . . . . . 8.2.5 Usage . . . . . . . . . . . . . . . 8.3 R cr ation . . . . . . . . . . . . . . . . . e e vii

133

9 Les d clarations e

9.1 D clarations de d nition et de r f rence . . . . . . . . . e e ee 9.1.1 D clarations de variables . . . . . . . . . . . . . e 9.1.2 D clarations de fonctions . . . . . . . . . . . . . e 9.1.3 D clarations d' tiquettes de structures et union . e e 9.2 Port e des d clarations . . . . . . . . . . . . . . . . . . . e e 9.3 Visibilit des identi cateurs . . . . . . . . . . . . . . . . e 9.4 Les espaces de noms . . . . . . . . . . . . . . . . . . . . 9.4.1 Position du probl me . . . . . . . . . . . . . . . . e 9.4.2 Les espaces de noms du langage C . . . . . . . . 9.5 Dur e de vie . . . . . . . . . . . . . . . . . . . . . . . . . e 9.6 Classes de m moire . . . . . . . . . . . . . . . . . . . . . e 9.6.1 Position du probl me . . . . . . . . . . . . . . . . e 9.6.2 Les sp ci cateurs de classe de m moire . . . . . . e e 9.7 La compilation s par e . . . . . . . . . . . . . . . . . . . e e 9.7.1 G n ralit s . . . . . . . . . . . . . . . . . . . . . ee e 9.7.2 La m thode du langage C . . . . . . . . . . . . . e 9.8 D nition de types . . . . . . . . . . . . . . . . . . . . . e 9.9 Utilit des typedef . . . . . . . . . . . . . . . . . . . . . e 9.9.1 Restriction d'un type de base . . . . . . . . . . . 9.9.2 D nition de type structure . . . . . . . . . . . . e 9.9.3 D nition de types opaques . . . . . . . . . . . . e 9.10 Quali catifs de type . . . . . . . . . . . . . . . . . . . . 9.11 Fonction a nombre variable de param tres . . . . . . . . e 9.11.1 Exemple 1 . . . . . . . . . . . . . . . . . . . . . . 9.11.2 Exemple 2 . . . . . . . . . . . . . . . . . . . . . . 9.12 Syntaxe des d clarations . . . . . . . . . . . . . . . . . . e 9.13 S mantique des d clarations . . . . . . . . . . . . . . . . e e 9.14 Discussion sur les d clarations . . . . . . . . . . . . . . . e 9.15 En pratique . . . . . . . . . . . . . . . . . . . . . . . . . 9.16 Un outil : cdecl . . . . . . . . . . . . . . . . . . . . . . . Diagnostic . . . . . . . . . . . . . . . . . . . . . . . . Manipulation de caract res ctype.h . . . . . . . . e Environnement local locale.h . . . . . . . . . . . Math matiques math.h . . . . . . . . . . . . . . . e 10.4.1 Fonctions trigonom triques et hyperboliques . e 10.4.2 Fonctions exponentielles et logarithmiques . . 10.4.3 Fonctions diverses . . . . . . . . . . . . . . . Branchements non locaux setjmp.h . . . . . . . . Manipulation des signaux signal.h . . . . . . . . Nombre variable de param tres stdarg.h . . . . . e Entr es sorties stdio.h . . . . . . . . . . . . . . . e 10.8.1 Op rations sur les chiers . . . . . . . . . . . e 10.8.2 Acc s aux chiers . . . . . . . . . . . . . . . . e 10.8.3 Entr es-sorties formatt es . . . . . . . . . . . e e viii . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

. 143 . 144 . 144 . 144 . 145 . 146 . 146 . 146 . 147 . 148 . 149 . 149 . 150 . 151 . 151 . 152 . 153 . 153 . 154 . 154 . 155 . 155 . 156 . 157 . 157 . 158 . 161 . 162 . 163 . 163 . 165 . 165 . 166 . 166 . 166 . 166 . 166 . 166 . 167 . 167 . 167 . 167 . 167 . 167

143

10 La biblioth que standard e
10.1 10.2 10.3 10.4

165

10.5 10.6 10.7 10.8

10.8.4 Entr es-sorties caract res . . . . . . . . . e e 10.8.5 Entr es-sorties binaires . . . . . . . . . . e 10.8.6 Position dans un chier . . . . . . . . . . 10.8.7 Gestion des erreurs . . . . . . . . . . . . . 10.9 Utilitaires divers stdlib.h . . . . . . . . . . . 10.9.1 Conversion de nombres . . . . . . . . . . 10.9.2 G n ration de nombres pseudo-al atoires ee e 10.9.3 gestion de la m moire . . . . . . . . . . . e 10.9.4 Communication avec l'environnement . . 10.9.5 Recherche et tri . . . . . . . . . . . . . . . 10.9.6 Arithm tique sur les entiers . . . . . . . . e 10.9.7 Gestion des caract res multi-octets . . . . e 10.10Manipulation de cha^nes string.h . . . . . . .
10.11Manipulation de la date et de l'heure time.h .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . .

. 168 . 168 . 168 . 168 . 168 . 168 . 169 . 169 . 169 . 169 . 169 . 169 . 169 . 170 . 171 . 172 . 175 . 175 . 176 . 177

A Les jeux de caract res e

A.1 Les normes . . . . . . . . . . . . . . . . A.2 Le code ascii . . . . . . . . . . . . . . A.2.1 Les codes ascii en octal . . . . A.2.2 Les codes ascii en hexad cimal e A.2.3 Les codes ascii en d cimal . . . e A.3 Les codes ISO-Latin-1 . . . . . . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

171

B Bibliographie C Ressources Internet D La grammaire
D.1 Les unit s lexicales . . . . . . . . . . e D.2 Les mots-cl s . . . . . . . . . . . . . e D.3 Les identi cateurs . . . . . . . . . . D.4 Les constantes . . . . . . . . . . . . D.5 Les cha^nes litt rales . . . . . . . . .
e D.6 Les op rateurs . . . . . . . . . . . . e D.7 La ponctuation . . . . . . . . . . . . D.8 Nom de chier d'inclusion . . . . . . D.9 Les nombres du pr processeur . . . . e D.10 Les expressions . . . . . . . . . . . . D.11 Les d clarations . . . . . . . . . . . . e D.12 Les instructions . . . . . . . . . . . . D.13 D nitions externes . . . . . . . . . . e D.14 Directives du pr processeur . . . . . e D.15 R f rences crois es de la grammaire ee e ix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

179 181
. 183 . 183 . 184 . 184 . 186 . 186 . 187 . 187 . 187 . 188 . 190 . 193 . 194 . 194 . 196

183

E Un bestiaire de types
E.1 E.2 E.3 E.4 E.5 E.6 E.7

Les types de base . . . . . . . . . . . . . Les tableaux . . . . . . . . . . . . . . . Les pointeurs . . . . . . . . . . . . . . . Les fonctions . . . . . . . . . . . . . . . Les num rations . . . . . . . . . . . . . e e Les structures, unions et champs de bits Les quali catifs . . . . . . . . . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . .

. 199 . 200 . 201 . 201 . 202 . 202 . 203 . 205 . 205 . 205 . 206 . 206 . 206 . 206 . 207 . 207 . 207 . 208 . 208 . 208 . 208 . 209 . 209

199

F Le b^tisier e

F.1 Erreur avec les op rateurs . . . . . . . . . . . . e F.1.1 Erreur sur une comparaison . . . . . . . F.1.2 Erreur sur l'a ectation . . . . . . . . . . F.2 Erreurs avec les macros . . . . . . . . . . . . . F.2.1 Un define n'est pas une d claration . e F.2.2 Un define n'est pas une initialisation F.2.3 Erreur sur macro avec param tres . . . e F.2.4 Erreur avec les e ets de bord . . . . . . F.3 Erreurs avec l'instruction if . . . . . . . . . . . F.4 Erreurs avec les commentaires . . . . . . . . . . F.5 Erreurs avec les priorit s des op rateurs . . . . e e F.6 Erreur avec l'instruction switch . . . . . . . . F.6.1 Oubli du break . . . . . . . . . . . . . . F.6.2 Erreur sur le default . . . . . . . . . . F.7 Erreur sur les tableaux multidimensionnels . . F.8 Erreur avec la compilation s par e . . . . . . . e e

205

x

Avant-propos
Au sujet de l'auteur
Je suis ing nieur au cnrs et je travaille dans un laboratoire de recherche de l'univere sit de Grenoble : le laboratoire clips http: www-clips.imag.fr. Toute noti cation e d'erreur ou toute proposition d'am lioration de ce document sera la bienvenue l'e-mail e a Bernard.Cassagne@imag.fr.

Au sujet de ce manuel
La litt rature technique nous a habitu deux styles d' criture de manuels : le style e ea e manuel de r f rence  et le style  guide de l'utilisateur  Les manuels de r f rence se ee ee donnent comme buts d'^tre exhaustifs et rigoureux. Les guides de l'utilisateur se donnent e comme but d'^tre didactiques. Cette partition vient du fait qu'il est quasiment impossible e sur des sujets complexes comme les langages de programmation d'^tre la fois rigoureux e a et didactique. Pour s'en persuader il su t de lire le texte d'une norme internationale. Ce manuel se place dans la cat gorie  guide de l'utilisateur  : son but est de permettre e a une personne sachant programmer, d'acqu rir les l ments fondamentaux du langage C. e ee Ce manuel pr sente donc chaque notion selon une gradation des di cult s et ne cherche e e pas ^tre exhaustif. Il comporte de nombreux exemples, ainsi que des exercices dont la ae solution se trouve dans le corps du texte, mais commence toujours sur une page di rente. e Le lecteur peut donc au choix, ne lire les solutions qu'apr s avoir programm sa solution e e personnelle, ou bien lire directement la solution comme si elle faisait partie du manuel. 


Les notions suppos es connues du lecteur e
Les notions suppos es connues du lecteur sont les concepts g n raux concernant les lane ee gages de programmation. En n du texte se trouve un glossaire qui regroupe des concepts g n raux et certains concepts propres du langage C. En cas de rencontre d'un mot inconnu, ee le lecteur est invit a s'y reporter. e

Un mot sur les probl mes de traduction e
Le document de r f rence concernant le langage C est la norme ansi d nissant le ee e langage. C'est un document crit en anglais technique, ce qui pose des probl mes de e e traduction : comment traduire les n ologismes invent s pour les besoins du langage? De e e mani re ne pas d router les lecteurs franais, je me suis impos de respecter les choix de e a e c e 1

traduction d'un grand diteur 1 de livres techniques, m^me quand je n'ai pas trouv ces e e e choix tr s heureux. J'ai donc utilis d clarateur, initialisateur et sp ci cateur bien que me e e e e semble-t-il, ils r^pent assez fort le palais quand on les prononce. a

Conventions syntaxiques
Les r gles de grammaires qui sont donn es dans le corps de ce manuel sont simpli es e e e dans un but didactique par rapport a la grammaire o cielle du langage. Cependant, le lecteur trouvera l'annexe D la grammaire sous une forme exhaustive et conforme la a a norme ansi. La typographie des r gles suit les conventions suivantes : e 1. les l ments terminaux du langage seront crits dans une fonte largeur constante, ee e a comme ceci : while. 2. les l ments non terminaux du langage seront crits en italique, comme ceci : ee e instruction. 3. les r gles de grammaires seront crites de la mani re suivante : e e e les parties gauches de r gles seront seules sur leur ligne, cadr es gauche et e e a suivies du signe deux points :. les di rentes parties droites possibles seront introduites par le signe  et e indent es sur la droite. e Exemple :
instruction : 



if if 



expression expression 



instruction 1 instruction 1

else

instruction 2

Ceci signi e qu'il y a deux mani res possibles de d river le non-terminal inse e truction. La premi re r gle indique qu'on peut le d river en : e e e if  expression  instruction 1 la deuxi me r gle indique qu'on peut aussi le d river en : e e e if  expression  instruction 1 else instruction 2 une partie droite de r gle pourra ^tre crite sur plusieurs lignes. Ceci permettra e e e de r ter une mani re possible de mettre en page le fragment de programme ee e C correspondant, de faon a obtenir une bonne lisibilit . c e Sans en changer la signi cation, l'exemple pr c dent aurait pu ^tre crit : ee e e
instruction : 

expression instruction 1  if  expression instruction 1 else instruction 2
if  



1. C'est masson qui a dit en franais 1 et 2 Cf. Bibliographie e e c

2

les l ments optionnels d'une r gle seront indiqu s en mettant le mot  option  ee e e en italique et dans une fonte plus petite a droite de l' l ment concern . ee e Par exemple, la r gle : e
d clarateur-init : e  d clarateur initialisateur option e

indique que d clarateur-init peut se d river soit en : e e
d clarateur initialisateur e

soit en :
d clarateur e

Remerciements
Beaucoup de personnes m'ont aid am liorer le manuscrit original en me signalant ea e de nombreuses erreurs et en me proposant des am liorations. Qu'elles soient toutes remere ci es de leurs lectures attentives et amicalement critiques, tout particuli rement Damien e e Genthial, Fabienne Lagnier, Xavier Nicollin et Serge Rouveyrol.

3

4

Chapitre 1

Les bases
Le but de ce chapitre est de pr senter les l ments de base du langage C, sous leur forme e ee la plus simple. Arriv au bout du chapitre, le lecteur sera capable d' crire des programmes e e l mentaires. ee

1.1 Les versions du langage C
Le langage C a subi au cours de son histoire deux grandes tapes de d nition. Il a e e t d ni une premi re fois par deux chercheurs des Laboratoires Bell, B. Kernighan et D. ee e e Ritchie, dans un livre intitul  The C Programming Language , publi en 1978. Cette e e version est appel e  Kernighan et Ritchie 78 , ou K&R 78 en abr g , ou encore le plus e ee souvent, simplement K&R. Suite l'extraordinaire succ s d'unix, qui induisit le succ s du langage C, la situation a e e devint confuse : plusieurs fournisseurs de compilateurs mirent sur le march des compie lateurs non conformes K&R car comportant des extensions particuli res. A la n des a e ann es 80, il devint n cessaire de mettre de l'ordre dans ce chaos et donc de normaliser e e le langage, t^che laquelle s'attela l'ansi 1, organisme de normalisation am ricain. La a a e norme ansi fut termin e en 1989. En 1990, l'iso 2 , organisme de normalisation internae tional, donc chapeautant l'ansi, adopta tel quel le standard ansi en tant que standard iso. Cette seconde version du langage C devrait donc s'appeler iso c, mais comme les acteurs importants du monde informatique sont de culture anglo-saxonne et que ceux-ci persistent l'appeler ansi c, presque? tout le monde fait de m^me. Dans ce manuel, a e nous suivrons l'usage g n ral, et utiliserons l'expression ansi c pour d signer la norme ee e commune a l'ansi et l'iso. Ce document d crit C ansi, avec parfois des r f rences C K&R, de mani re pere ee a e a mettre au lecteur de comprendre les sources crits avant l'apparition de la norme. e

1.2 Langage et biblioth que standard e
Le langage C a t conu pour l' criture de syst mes, en particulier le syst me unix. ee c e e e Pour cette raison, ses concepteurs ont fait une s paration nette entre ce qui est purement e
1. American National Standards Institute 2. International Standards Organization

5

algorithmique d clarations, instructions, etc. et tout ce qui est interaction avec le syse t me entr es sorties, allocation de m moire, etc. qui est r alis par appel de fonctions e e e e e se trouvant dans une biblioth que dite biblioth que standard. Cette coupure se retrouve e e dans la norme qui est compos e essentiellement de deux grands chapitres, les chapitres e  langage  et  biblioth que  .    e  Ce manuel se donne comme objectif de donner une vue d'ensemble du langage, mais pas de la biblioth que standard. De la biblioth que standard ne seront pr sent es de mani re e e e e e compl te que les fonctions permettant de r aliser les entr es-sorties et la gestion m moire. e e e e Cependant, la liste exhaustive des noms des fonctions de la biblioth que, class s par type e e d'utilisation, est donn e dans le chapitre 10. e

1.3 Les phases de compilation
Les compilateurs C font subir deux transformations aux programmes : 1. un pr processeur r alise des transformations d'ordre purement textuel, pour rendre e e des services du type inclusion de source, compilation conditionnelle, et traitement de macros ; 2. le compilateur proprement dit prend le texte g n r par le pr processeur et le traduit e ee e en instructions machine. La fonction de pr processeur est assez souvent impl ment e par un programme s par e e e e e cpp sous unix qui est automatiquement appel par le compilateur. e

1.4 Les jeux de caract res e
Le lecteur non familiaris avec les probl mes de codage de caract res peut se reporter e e e a l'annexe A, o ces probl mes sont d velopp s. u e e e Le langage C n'impose pas un jeu de caract res particulier. Par contre tout le langage e mots-cl s, op rateurs, etc. est d ni en utilisant les caract res ascii. M^me les identi e e e e e cateurs doivent ^tre crits avec l'alphabet anglais. Par contre, le jeu de caract res utilis e e e e pour les constantes caract re, les cha^nes de caract res et les commentaires est d pendant e
e e de l'impl mentation. e Pendant tr s longtemps les programmeurs non anglophones ont utilis l'ascii faute de e e mieux, pour programmer en C. Actuellement, si on est dans le monde unix, il ne doit pas y avoir de probl me pour disposer d'un environnement de travail la fen^tre, le shell, e e l' diteur, le compilateur enti rement la norme iso-8859. Dans ce manuel, on suppose e e a que le lecteur dispose d'un tel environnement : les exemples donn s sont crits en iso-8859. e e

1.5 Les unit s lexicales e
Le langage comprends 6 types d'unit s lexicales : les mots-cl s, les identi cateurs, les e e constantes, les cha^nes, les op rateurs et les signes de ponctuation.
e 6

1.5.1 Les mots-cl s e

Le langage C est un langage mots-cl s, ce qui signi e qu'un certain nombre de a e mots sont r serv s pour le langage lui-m^me et ne peuvent donc pas ^tre utilis s comme e e e e e identi cateurs. La liste exhaustive des mots-cl s est la suivante : e
auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while

Attention

Si le compilateur produit un message d'erreur syntaxique incompr hensible il est ree command d'avoir le r exe de consulter la liste des mots cl s pour v ri er que l'on a pas e e e e pris comme identi cateur un mot-cl . Si le lecteur d sire ^tre convaincu, il lui est sugg r e e e ee de donner le nom long une variable enti re. a e Le but d'un identi cateur est de donner un nom a une entit du programme variable, e proc dure, etc. Les identi cateurs sont form s d'une suite de lettres, de chi res et du signe e e soulign , suite dont le premier caract re ne peut pas ^tre un chi re. Les lettres formant e e e les identi cateurs peuvent ^tre majuscules ou minuscules, mais doivent faire partie de e l'alphabet anglais : les lettres accentu es sont interdites. Les noms var1, PremierIndex, e i_tab, _deb sont des identi cateurs valides, mais 1i et i:j ne le sont pas. Un compilateur a le droit de tronquer les identi cateurs internes ceux qui ne sont pas export s un diteur de liens au del d'une certaine longueur. Cette limite d pend de e a e a e l'impl mentation, mais ne doit pas ^tre inf rieure a 31 caract res. e e e e De la m^me mani re, les identi cateurs externes export s a un diteur de liens poure e e e ront ^tre tronqu s au del d'une certaine longueur. Cette limite est g n ralement plus e e a ee s v re, mais ne peut ^tre inf rieure a 6 caract res. De surcro^t, la distinction entre minusee e e e
cules et majuscules n'est pas garantie au contraire des noms internes, pour lesquels cette distinction est garantie.

1.5.2 Les identi cateurs

1.6 Les commentaires
Syntaxe : Les commentaires d butent par e
* *

et se terminent par * . Exemple :
*

Ceci est un commentaire

Toute occurrence de * est interpr t e comme le d but d'un commentaire sauf dans ee e une cha^ne litt rale, ou un commentaire les commentaires ne peuvent donc pas ^tre
e e imbriqu s. e 7

Recommandations : Dans le domaine g n ral de la programmation, pas seulement le langage C, il est ee admis qu'il faille commenter selon les niveaux suivants : unit de compilation : pour indiquer le nom de l'auteur, les droits de copyright, e la date de cr ation, les dates et auteurs des di rentes modi cations, ainsi que e e la raison d'^tre de l'unit ; e e proc dure : pour indiquer les param tres et la raison d'^tre de la proc dure ; e e e e groupe d'intructions : pour exprimer ce que r alise une fraction signi cative e d'une proc dure ; e d claration ou instruction : le plus bas niveau de commentaire. e Pour le niveau unit de compilation, voici un exemple tir du source de perl : e e
* * * * * * * * * * * * * * * * Copyright c 1991, Larry Wall You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the README file. $Log: perl.c,v $ Revision 4.0.1.8 1993 02 05 19:39:30 lwall Revision 4.0.1.7 92 06 08 14:50:39 lwall Revision 4.0.1.3 91 06 07 11:40:18 lwall Revision 4.0.1.2 91 06 07 11:26:16 lwall Revision 4.0.1.1 91 04 11 17:49:05 lwall Revision 4.0 91 03 20 01:37:44 lwall 4.0 baseline.

Pour le niveau de la proc dure, je trouve agr able de r aliser des esp ces de care e e e touches permettant de d couper visuellement un listing en ses di rentes proc dures, e e e comme ceci par exemple :
****************************************************************************** * * * strcpy * * * * But: * * copie une cha^ne dans une autre
* * * * Interface: * * s1 : cha^ne destination
* * s2 : cha^ne source
* * * ******************************************************************************

En ce qui concerne le niveau groupe d'instruction, il est classique de faire une mise en page comme dans l'exemple suivant tir du source de dvips 3 : e
*

3. dvips est un traducteur en PostScript du format g n r par TeX e ee

8

* * * * * * * *

If nothing above worked, then we get desperate. We attempt to open the stupid font at one of a small set of predefined sizes, and then use PostScript scaling to generate the correct size. We much prefer scaling up to scaling down, since scaling down can omit character features, so we try the larger sizes first, and then work down.

Pour le niveau d claration ou instruction, on commentera sur la m^me ligne. Exemple e e tir du source du compilateur gnu cc : e
char *name; struct function_unit *next; int multiplicity; int simultaneity; struct range ready_cost; struct range issue_delay; * * * * Function unit name. * Next function unit. * Number of units of this type. * Maximum number of simultaneous insns on this function unit or 0 if unlimited. * Range of ready cost values. * * Range of issue delay values. *

*

Attention
L'erreur classique avec les commentaires est d'oublier la s quence fermante * . Dans e ce cas, le compilateur va consid rer que le commentaire se poursuit jusqu' la n du e a prochain commentaire et ceci peut ne pas g n rer d'erreur syntaxique. ee Exemple : instruction
instruction ... instruction
* * premier commentaire

instruction On voit que dans ce cas, tout un ensemble d'instructions sera ignor par le compilae 4. teur sans g n rer le moindre message d'erreur ee

second commentaire

*

Un commentaire ne peut pas contenir un commentaire, il n'est donc pas possible de mettre en commentaire un morceau de programme comportant d j des commenea 5. taires
4. Dans 5 , Peter Van der Linden donne un exemple amusant de ce bug. Dans un compilateur, l'e cacit e de l'algorithme de hachage de la table des identi cateurs d pendait de la bonne initialisation d'une variable. e Dans le code initial, l'initialisation avait t mise involontairement dans un commentaire provoquant une ee initialisation par d faut z ro. La simple correction du bug, t gagner 15 d'e cacit au compilateur ! e a e e 5. Voir cependant F.4

9

1.7 Les types de base
1.7.1 Les caract res e
Le mot-cl d signant les caract res est char. Un objet de ce type doit pouvoir contenir e e e le code de n'importe quel caract re de l'ensemble des caract res utilis sur la machine. e e e Le codage des caract res n'est pas d ni par le langage : c'est un choix d'impl mentation. e e e Cependant, dans la grande majorit des cas, le code utilis est le code dit ascii, ou un e e surensemble comme par exemple la norme iso-8859.

Attention
Le type caract re est original par rapport ce qui se fait habituellement dans les e a langages de programmation. La norme pr cise clairement qu'un objet de type caract re e e peut ^tre utilis dans toute expression o un objet de type entier peut ^tre utilis . Par e e u e e exemple, si c est de type char, il est valide d' crire c + 1 : cela donnera le caract re e e suivant dans le code utilis sur la machine. e

1.7.2 Les entiers
Le mot cl d signant les entiers est int. Les entiers peuvent ^tre a ect s de deux types e e e e d'attributs : un attribut de pr cision et un attribut de repr sentation. e e Les attributs de pr cision sont short et long. Du point de vue de la pr cision, on peut e e avoir trois types d'entiers : short int, int et long int. Les int sont impl ment s sur ce e e qui est un mot  naturel  de la machine. Les long int sont impl ment s si possible plus e e grands que les int, sinon comme des int. Les short int sont impl ment s si possible e e plus courts que les int, sinon comme des int. Les impl mentations classiques mettent les e short int sur 16 bits, les long int sur 32 bits, et les int sur 16 ou 32 bits selon ce qui est le plus e cace. L'attribut de repr sentation est unsigned. Du point de vue de la repr sentation, on e e peut avoir deux types d'entiers : int et unsigned int. Les int permettent de contenir des entiers sign s, tr s g n ralement en repr sentation en compl ment 2, bien que cela e e ee e e a ne soit pas impos par le langage. Les unsigned int permettent de contenir des entiers e non sign s en repr sentation binaire. e e On peut combiner attribut de pr cision et attribut de repr sentation et avoir par e e exemple un unsigned long int. En r sum , on dispose donc de six types d'entiers : e e int, short int, long int tous trois sign s et unsigned int, unsigned short int e et unsigned long int.

1.7.3 Les ottants
Il existe trois types de ottants correspondants trois pr cisions possibles. En allant a e de la pr cision la plus faible vers la plus forte, on dispose des types float, double et e long double. La pr cision e ectivement utilis e pour chacun de ces types d pend de e e e l'impl mentation. e 10

1.8 Les constantes
1.8.1 Les constantes enti res e
Syntaxe : On dispose de 3 notations pour les constantes enti res : d cimale, octale et hexad e e e cimale. Les constantes d cimales s' crivent de la mani re usuelle ex : 372. Les constantes e e e octales doivent commencer par un z ro et ne comporter que des chi res octaux e ex : 0477. Les constantes hexad cimales doivent commencer par 0x ou 0X et ^tre e e compos es des chi res de 0 a 9, ainsi que des lettres de a f sous leur forme majuscule e a ou minuscule ex : 0x5a2b, 0X5a2b, 0x5A2B. Une constante enti re peut ^tre su x e par la lettre u ou U pour indiquer qu'elle e e e doit ^tre interpr t e comme tant non sign e. Elle peut galement ^tre su x e par e ee e e e e e la lettre l ou L pour lui donner l'attribut de pr cision long. e S mantique : e Le type d'une constante enti re est le premier type, choisi dans une liste de types, e permettant de repr senter la constante : e liste de types forme de la constante pas de su xe, d cimal e int, long int, unsigned long int pas de su xe, octal ou hexad cimal int, unsigned int, long int, unsigned e su x par u ou U e unsigned int, unsigned long int su x par l ou L e long int, unsigned long int su x par u ou U et l ou L e unsigned long int

long int

Attention
Ces conventions d' criture des constantes ne respectent pas l' criture math matique, e e e puisque 010 devant ^tre interpr t en octal, n'est pas gal 10. e ee e a

1.8.2 Les constantes caract res e
Syntaxe : Une constante caract re s' crit entour e du signe '. La r gle g n rale consiste crire e e e e ee ae le caract re entour du signe ' ; par exemple, la constante caract re correspondant e e e au caract re g s' crit 'g'. e e 11

Les cas particuliers
Les cas particuliers sont trait s par une s quence d' chappement introduite par le e e e caract re . e Caract res ne disposant pas de repr sentation imprimable. e e 1. On peut les d signer par la notation ' nb' o nb est le code en octal du e u caract re. Exemple : e e constante caract re s mantique e ' 0' null ' 12' newline ' 15' carriage return ' 33' escape 2. On peut les d signer par la notation ' xnb' o nb est le code en hexad e u e cimal du caract re. Exemple : e constante caract re s mantique e e ' x0A' newline ' x0D' return ' x1B' escape 3. Certains d'entre eux, utilis s tr s fr quemment, disposent d'une notation e e e particuli re. Il s'agit des caract res suivants : e e s mantique e constante caract re e ' n' new line ' t' horizontal tabulation ' v' vertical tabulation ' b' back space ' r' carriage return ' f' form feed ' a' audible alert Caract res disposant d'une repr sentation imprimable mais devant ^tre d sign s e e e e e par une s quence d' chappement. e e constante caract re s mantique e e
' '' ' ' '

Caract res disposant d'une repr sentation imprimable et pouvant ^tre d sign s e e e e e soit par une s quence d' chappement soit par eux-m^mes. e e e constante caract re s mantique e e ' "' ou '"' " ' ?' ou '?' ? S mantique : e Une constante caract re est de type int et a pour valeur le code du caract re dans e e le codage utilis par la machine. e 12

Note
Pourquoi diable les deux caract res " et ? disposent ils de deux notations possibles? e Le caract re " peut ^tre repr sent par la notation ' "' parce que celle-ci doit e e e e ^tre utilis e dans les cha^nes de caract res voir plus loin 1.9. Pour des raisons de e e
e sym trie, les concepteurs du langage n'ont pas voulu qu'une notation valable pour e une cha^nes de caract res ne soit pas valable pour un caract re.
e e Le caract re ? est un cas part cause de l'existence des trigraphes. Les trie a a graphes sont des s quences de trois caract res permettant de d signer les caract res e e e e  ^ | ~. En e et, les terminaux conformes la norme iso 646:1983 ont a remplac ces caract res par des caract res nationaux. Les franais, par exemple, e e e c connaissent bien le probl me des et des qui se transforment en et . e e e La norme ansi a d ni les 9 trigraphes suivants : e e trigraphe s mantique
??= ?? ?? ?? ??' ?? ?? ??! ??

^

| ~

1.8.3 Les constantes ottantes
Syntaxe : La notation utilis e est la notation classique par mantisse et exposant. La mantisse e est compos e d'une partie enti re suivie du signe . point suivi de la partie frace e tionnaire. La partie enti re et la partie fractionnaire sont exprim es en d cimal et e e e l'une ou l'autre peuvent ^tre omises. e L'exposant est introduit par la lettre e sous la forme minuscule ou majuscule. L'exposant est un nombre d cimal ventuellement sign . e e e Une constante ottante peut ^tre su x e par l'une quelconque des lettres f, F, l, L. e e S mantique : e Une constante non su x e a le type double. Une constante su x e par f ou F a le e e type float. Une constante su x e par l ou L a le type long double. e La valeur de la constante mantisse e exposant est mantisse 10exposant . Si la valeur r sultante ne correspond pas au type, la valeur est arrondie vers une e valeur sup rieure ou inf rieure le choix d pend de l'impl mentation. e e e e 13

Exemples : notation C notation math matique e 2. 2 .3 03 2.3 23 2e4 2  104 2.e4 2  104 0 3  104 .3e4 2.3e4 2 3  104 2.3e-4 2 3  10,4
: : : : :

1.9 Les cha^nes de caract res litt rales
e e
Une cha^ne de caract res litt rale est une suite de caract res entour s du signe ".
e e e e Exemple :
"ceci est une cha^ne"

Toutes les s quences d' chappement d nies en 1.8.2 sont utilisables dans les cha^nes. e e e
Exemple :
"ligne 1 nligne 2 nligne 3"

Le caract re suivi d'un passage la ligne suivante est ignor . Cela permet de faire e a e tenir les longues cha^nes sur plusieurs lignes de source. Exemple :

"ceci est une tr s tr s longue cha^ne que l'on fait tenir e e
sur deux lignes de source"

Si deux cha^nes litt rales sont adjacentes dans le source, le compilateur concat ne les
e e deux cha^nes. Exemple : "Hello " "World!!" est quivalent "Hello World!!".
e a Le compilateur rajoute a la n de chaque cha^ne un caract re mis a z ro. Le caract re
e e e dont la valeur est z ro est appel null dans le code ASCII. Cette convention de n de e e cha^ne est utilis e par les fonctions de la biblioth que standard. Exemple : sur rencontre
e e de "Hello!" le compilateur implantera en m moire 7 caract res H, e, l, l, o, !, 0. e e Dans une cha^ne de caract res litt rale, le caract re " doit ^tre d sign par la s quence
e e e e e e e d' chappement, alors que ' peut ^tre d sign par sa s quence d' chappement ou par luie e e e e e m^me. e

1.10 Les constantes nomm es e
Il y a deux faons de donner un nom a une constante : soit en utilisant les possibilit s c e du pr processeur, soit en utilisant des num rations. e e e 14

1.10.1 Les de ne 
define

Lorsque le pr processeur lit une ligne du type : e
identi cateur reste-de-la-ligne

il remplace dans toute la suite du source, toute nouvelle occurrence de identi cateur par reste-de-la-ligne. Par exemple on peut crire : e 
define PI 3.14159 3.14159.

et dans la suite du programme on pourra utiliser le nom PI pour d signer la constante e

Attention
Une telle d nition de constante n'est pas une d claration mais une commande du e e pr processeur. Il n'y a donc pas de ; la n. Rappelons que le pr processeur ne compile e a e pas, il fait des transformations d'ordre purement textuel. Si on crit : e 
define PI 3.14159;

le pr processeur remplacera toute utilisation de PI par 3.14159; et par exemple, remplae cera l'expression PI 2 par 3.14159; 2 ce qui est une expression incorrecte. Dans une telle situation, le message d'erreur ne sera pas mis sur la ligne fautive le define, mais e sur une ligne correcte celle qui contient l'expression PI 2, ce qui g^nera la d tection e e de l'erreur.

1.10.2 Les num rations e e
enum enum

On peut d nir des constantes de la mani re suivante : e e liste-d'identi cateurs Par exemple :
LUNDI, MARDI, MERCREDI, JEUDI, VENDREDI, SAMEDI, DIMANCHE ;

d nit les identi cateurs LUNDI, ... DIMANCHE comme tant des constantes de type int, et e e leur donne les valeurs 0, 1, ... 6. Si on d sire donner des valeurs particuli res aux constantes, e e cela est possible :
enum FRANCE = 10, ESPAGNE = 20, ITALIE = 30 ;

Il n'est pas n cessaire de donner une valeur toutes les constantes : e a
enum FRANCE = 10, LUXEMBOURG, BELGIQUE, ESPAGNE = 20, ITALIE = 30 ;

donnera la valeur 11 LUXEMBOURG et 12 a BELGIQUE. a Il est d'usage au moins dans le monde unix de donner un nom enti rement en majuse cules aux constantes nomm es d'un programme. Mon opinion est que ceci est une bonne e convention, qui accro^t la lisibilit des programmes.
e 15

Remarque

1.11 D clarations de variables ayant un type de base e
Une telle d claration se fait en faisant suivre un type par une liste de noms de variables. e Exemple :
int i; int i,j; short int k; float f; double d1,d2; * * * * * d claration e d claration e d claration e d claration e d claration e de de de de de la variable i de type int deux variables i et j de type int la variable k de type short int la variable f de type float deux variables d1 et d2 de type double * * * * *

Il est possible de donner une valeur initiale aux variables ainsi d clar es. Exemple : e e
int i = 54; int i = 34, j = 12;

1.12 Les op rateurs les plus usuels e
1.12.1 L'a ectation
Syntaxe : expression : En C, l'a ectation est un op rateur et non pas une instruction. e

expression Dans le jargon C, une lvalue est une expression qui doit d livrer une variable par e opposition a une constante. Une lvalue peut ^tre par exemple une variable simple, e un l ment de tableau, mais pas une constante. Cette notion permet d'exprimer dans ee la grammaire l'impossibilit d' crire des choses du genre 1 = i qui n'ont pas de sens. e e Exemples d'a ectation :
= i = 3 f = 3.4 i = j + 1 

lvalue

S mantique : e L'op rateur d'a ectation a deux e ets : e 1. il r alise un e et de bord consistant a ecter la valeur de expression la e a a variable d sign e par la lvalue ; e e 2. il d livre la valeur ainsi a ect e, valeur qui pourra ^tre utilis e dans une exe e e e pression englobant l'a ectation. Exemple :
i = j = k + 1

16

La valeur de k est a ect e j et cette valeur est le r sultat de l'expression j e a e on y ajoute 1 et le r sultat est a ect i. e ea

= k ;

Conversions de type : Lorsque la valeur de l'expression est a ect e a la lvalue, la valeur est ventuellement e e convertie dans le type de la lvalue. On peut par exemple a ecter une expression enti re un ottant. e a

1.12.2 L'addition
Syntaxe : expression : 

+ expression  expression 1 + expression 2

S mantique : e Les deux expressions sont valu es, l'addition r alis e, et la valeur obtenue est la e e e e valeur de l'expression d'addition. La s mantique de + expression est celle de 0 + e expression. L'ordre dans lequel les deux expressions sont valu es, n'est pas d termin . Si exe e e e pression 1 et expression 2 font des e ets de bords, on n'est donc pas assur de l'ordre e dans lequel ils se feront. Apr s valuation des expressions, il peut y avoir conversion de type de l'un des e e op randes, de mani re a permettre l'addition. On pourra par exemple faire la somme e e d'une expression d livrant un ottant et d'une expression d livrant un entier : l'entier e e sera converti en ottant et l'addition sera r alis e entre ottants. e e

1.12.3 La soustraction
Syntaxe : L'op rateur peut ^tre utilis de mani re unaire ou binaire : e e e e
expression : 

- expression  expression 1 - expression 2

S mantique : e Les deux expressions sont valu es, la soustraction r alis e, et la valeur obtenue est e e e e la valeur de l'expression soustraction. La s mantique de - expression est celle de 0 e - expression. Les m^mes remarques concernant l'ordre d' valuation des op randes ainsi que les e e e ventuelles conversions de type faites au sujet de l'addition s'appliquent la souse a traction. 17

1.12.4 La multiplication
Syntaxe : expression : 

expression 1

*

expression 2

S mantique : e Les deux expressions sont valu es, la multiplication r alis e, et la valeur obtenue e e e e est la valeur de l'expression multiplicative. Les m^mes remarques concernant l'ordre d' valuation des op randes ainsi que les e e e ventuelles conversions de type faites au sujet de l'addition s'appliquent la multie a plication.

1.12.5 La division
Syntaxe : expression : 

expression 1

expression 2

S mantique : e Contrairement d'autres langages, le langage C ne dispose que d'une seule notation a pour d signer deux op rateurs di rents : le signe d signe la fois la division enti re e e e e a e et la division entre ottants. Si expression 1 et expression 2 d livrent deux valeurs enti res, alors il s'agit d'une e e division enti re. Si l'une des deux expressions au moins d livre une valeur ottante, e e il s'agit d'une division entre ottants. Dans le cas de la division enti re, si les deux op randes sont positifs, l'arrondi se e e fait vers z ro, mais si au moins un des deux op randes est n gatif, la faon dont se e e e c fait l'arrondi d pend de l'impl mentation mais il est g n ralement fait vers z ro. e e ee e Exemple : 13 2 d livre la valeur 6 et -13 2 ou 13 -2 peuvent d livrer -6 ou e e -7 mais le r sultat sera g n ralement -6. e ee Les remarques concernant l'ordre d' valuation des op randes faites au sujet de l'ade e dition s'appliquent galement la division. Les remarques concernant les ventuelles e a e conversion de type faites au sujet de l'addition s'appliquent la division entre ota tants.

1.12.6 L'op rateur modulo e
Syntaxe : expression : 

expression 1 

expression 2

S mantique : e Les deux expressions sont valu es et doivent d livrer une valeur de type entier, e e e on value le reste de la division enti re de expression 1 par expression 2 et la valeur e e obtenue est la valeur de l'expression modulo. 18

Si au moins un des deux op randes est n gatif, le signe du reste d pend de l'impl e e e e mentation, mais il est g n ralement pris du m^me signe que le dividende. Exemples : ee e 13  2 d livre 1 e -13  2 d livre g n ralement -1 e ee 13  -2 d livre g n ralement 1. e ee Les choix d'impl mentation faits pour les op rateurs division enti re et modulo e e e doivent ^tre coh rents, en ce sens que l'expression : e e b * a b + a  b o a et b sont des entiers u doit avoir pour valeur a.

1.12.7 Les op rateurs de comparaison e
Syntaxe : expression : 

expression 1 op rateur expression 2 e o op rateur peut ^tre l'un des symboles suivants : u e e
op rateur e
= = == !=

s mantique e strictement sup rieur e strictement inf rieur e sup rieur ou gal e e inf rieur ou gal e e gal e di rent e

S mantique : e Les deux expressions sont valu es puis compar es, la valeur rendue est de type int e e e et vaut 1 si la condition est vraie, et 0 sinon. On remarquera que le type du r sultat est int, car le type bool en n'existe pas. e e

1.13 Les instructions les plus usuelles
1.13.1 Instruction expression
Syntaxe : instruction :  expression
;

S mantique : e L'expression est valu e, et sa valeur est ignor e. Ceci n'a donc de sens que si l'exe e e pression r alise un e et de bord. Dans la majorit des cas, il s'agira d'une expression e e d'a ectation. Exemple :
i = j + 1;

19

Remarque
D'apr s la syntaxe, on voit qu'il est parfaitement valide d' crire l'instruction e e
i + 1;

mais ceci ne faisant aucun e et de bord, cette instruction n'a aucune utilit . e

1.13.2 Instruction compos e e
Syntaxe : instruction : 

liste-de-d clarationsoption e liste-d'instructions

S mantique : e Le but de l'instruction compos e est double, elle permet : e 1. de grouper un ensemble d'instructions en lui donnant la forme syntaxique d'une seule instruction ; 2. de d clarer des variables qui ne seront accessible qu' l'int rieur de l'instruction e a e compos e structure classique de 'blocs'. e

Remarques sur la syntaxe
il n'y a pas de s parateur dans liste-d'instructions les points virgules sont des tere minateurs pour les instructions qui sont des expressions ; les accolades jouent le r^le des mots cl s begin et end que l'on trouve dans certains o e langages Pascal, PL 1, etc..

1.13.3 Instruction if
Syntaxe : instruction : 



if if 



expression expression 



instruction 1 instruction 1

else

instruction 2

S mantique : e expression est valu e, si la valeur rendue est non nulle, on ex cute instruction 1 , e e e sinon on ex cute instruction 2 si elle existe. e

Remarques sur la syntaxe
1. Attention au fait que expression doit ^tre parenth s e ; e ee 2. La partie then de l'instruction n'est pas introduite par un mot cl : pas de e comme dans certains langages. 20
then

3. Lorsqu'il y a ambigu
t sur l'instruction if dont d pend une partie else, l'ambigu
t e e e est lev e en faisant d pendre le else de l'instruction if la plus proche. e e Par exemple, si on crit : e
if a b if c d u = v; else i = j; c d.

le else sera celui du if crire : e
if a b d u = v;

Si on voulait qu'il en soit autrement, il faudrait

if c

else i = j;

Etant donn que l'instruction if teste l' galit z ro de expression, celle-ci n'est e e ea e pas n cessairement une expression de comparaison. Toute expression d livrant une valeur e e pouvant ^tre compar e z ro est valide. e e a e

Remarques sur la s mantique e

Exemples d'instructions if
if a if x ... else ... * liste d'instructions * b max = a; else max = b; y * liste d'instructions *

if a ...

*

e quivalent if a != 0 a

*

1.14 Inclusion de source
Nous avons d j vu que la premi re phase de compilation est le traitement r alis par ea e e e le pr processeur qui rend des services d'inclusion de source, de compilation conditionnelle e et de traitement de macros. Nous allons voir dans ce chapitre ses capacit s d'inclusion de e source. Lorsqu'on d veloppe un gros logiciel, il est g n ralement n cessaire de le d couper e ee e e en unit s de compilation de taille raisonnable. Une fois un tel d coupage r alis , il est e e e e 21

courant que plusieurs unit s aient certaines parties communes par exemple des d nitions e e de constantes l'aide de commandes define. a De faon a viter la r p tition de ces parties communes, le langage C o re une facilit c e ee e d'inclusion de source qui est r alis e a l'aide de la commande include du pr processeur. e e e Lorsque le pr processeur rencontre une ligne du type : e include " nom-de- chier " ou include nom-de- chier il remplace cette ligne par le contenu du chier nom-de- chier. La mani re dont se fait la recherche du chier inclure est d pendante de l'impl mene a e e tation. Dans le syst me unix, il est traditionnel de se conformer la r gle suivante : e a e si on utilise et , le chier est un chier syst me, il sera recherch dans un ou plue e sieurs r pertoires syst mes connus du compilateur, comme par exemple usr include. e e si on utilise ", le chier inclure est un chier utilisateur, il sera recherch dans a e l'espace de chiers de l'utilisateur, par exemple le r pertoire courant. e

1.15 Les proc dures et les fonctions e
1.15.1 D nition d'une fonction e
Syntaxe : d nition-de-fonction : e  type identi cateur 

liste-de-d clarations-de-param tres e e 

liste-de-d clarations option e liste-d'instructions

Dans le jargon C, l'ensemble : type identi cateur  liste-de-d clarations-de-param tres  e e porte le nom bizarre de prototype de fonction . S mantique : e type est le type de la valeur rendue par la fonction ; identi cateur est le nom de la fonction ; liste-de-d clarations-de-param tres est la liste s par s par des virgules e e e e des d clarations des param tres formels. La liste-de-d clarations option permet si e e e besoin est, de d clarer des variables qui seront locales la fonction, elles seront donc e a inaccessibles de l'ext rieur. La liste-d'instructions est l'ensemble des instructions e qui seront ex cut es sur appel de la fonction. Parmi ces instructions, il doit y avoir e e au moins une instruction du type :
return

Note

expression

;

Lors de l'ex cution d'une telle instruction, expression est valu e, et le contr^le e e e o d'ex cution est rendu a l'appelant de la fonction. La valeur rendue par la fonction e est celle de expression. 22

Exemple
int sum_squareint i,int j * * * la fonction sum_square d livre un int e ses param tres formels sont les int i et j e d claration des variables locales e * * *

int resultat; resultat = i*i + j*j; returnresultat;

*

retour a l'appelant en d livrant r sultat e e

*

Instruction return
L'instruction return est une instruction comme une autre, il est donc possible d'en utiliser autant qu'on le d sire dans le corps d'une fonction. Exemple : e
int maxint i,int j * * * la fonction max d livre un int e ses param tres formels sont les int i et j e pas de variables locales pour max * * *

if i

j returni; else returnj;

Si la derni re instruction ex cut e par une fonction n'est pas une instruction return, e e e la valeur rendue par la fonction est ind termin e. e e

Les param tres formels e
Dans le cas o une fonction n'a pas de param tres formels, le mot cl void est mis en u e e tant que liste-de-d clarations-de-param tres. Exemple : e e
double pivoid return3.14159; * * pas de param tres formels e pas de variables locales * *

Attention
La syntaxe des d clarations pour les param tres formels et les variables n'est pas la e e m^me. Quand on a besoin de d clarer deux variables du m^me type, on peut utiliser deux e e e d clarations : e
int i; int j;

Mais on peut aussi n'utiliser qu'une d claration pour d clarer les deux variables : e e
int i,j;

23

Cette possibilit n'existe pas pour une liste de param tres formels. Il n'est pas possible e e d' crire max de la mani re suivante : e e
int maxint i,j ... * incorrect *

1.15.2 Appel d'une fonction
Syntaxe : expression : 

identi cateur 

liste-d'expressions 

S mantique : e Les expressions de liste-d'expressions sont valu es, puis pass es en tant que pae e e ram tres e ectifs la fonction de nom identi cateur, qui est ensuite ex cut e. La e a e e valeur rendue par la fonction est la valeur de l'expression appel de fonction. Exemple :
int a,b,m,s; double d; s = sum_squarea,b; m = maxa,b; d = pi; * * * appel de sum_square appel de max appel de pi * * *

Attention
1. Dans le cas d'une fonction sans param tre, la liste-d'expressions doit ^tre vide : il e e n'est pas possible d'utiliser le mot cl void en tant que param tre e ectif. e e
d = pivoid; * appel incorrect de pi *

2. L'ordre d' valuation des param tres e ectifs n'est pas sp ci . Si certains de ceuxe e e e ci r alisent des e ets de bords, l'ordre dans lequel ils se feront n'est pas garanti. e Exemple :
sum_squarefx,gy;

La fonction g sera peut-^tre ex cut e avant f. e e e 24

1.15.3 Les proc dures e

Le langage C ne comporte pas strictement parler le concept de proc dure. Cependant, a e les fonctions pouvant r aliser sans aucune restriction tout e et de bord qu'elles d sirent, e e le programmeur peut r aliser une proc dure a l'aide d'une fonction qui ne rendra aucune e e valeur. Pour exprimer l'id e de  aucune valeur , on utilise le mot-cl void. Une proc dure e e e sera donc impl ment e sous la forme d'une fonction retournant void et dont la partie listee e d'instructions ne comportera pas d'instruction return. Lors de l'appel de la proc dure, il faudra ignorer la valeur rendue c'est dire ne pas e a l'englober dans une expression.

Exemple
void print_addint i,int j int r; r = i + j; ... * * la proc dure et ses param tres formels e e une variable locale print_add a * *

*

instruction pour imprimer la valeur de r *

void printsvoid int a,b; a = 12; b = 45; print_adda,b; print_add13,67;

* *

une proc dure sans param tres e e variables locales prints a

* *

* *

appel de print_add un autre appel print_add a

* *

Probl me de vocabulaire e
Dans la suite du texte, nous utiliserons le terme de fonction pour d signer indi reme e ment une proc dure ou une fonction, chaque fois qu'il ne sera pas n cessaire de faire la e e distinction entre les deux.

1.15.4 Fonctions imbriqu es e

A l'inverse de certains langages, les fonctions imbriqu es n'existent pas dans le langage e C. Il n'est donc pas possible qu'une fonction ne soit connue qu' l'int rieur d'une autre a e fonction.

1.15.5 R cursivit e e
int factoint n

Il n'y a rien de sp cial faire la d claration d'une fonction pour qu'elle puisse ^tre e a a e e appel e de mani re r cursive. Voici un exemple de factorielle : e e e

25

if n == 1 return1; else returnn * facton-1;

1.15.6 R f rence une fonction externe ee a

Quand on d sire utiliser une fonction qui est d nie ailleurs, il est n cessaire de la e e e d clarer comme tant externe. Cela se fait en pr xant l'en-t^te de la fonction du mot cl e e e e e extern, comme ceci :
extern int sum_squareint i, int j;

Le cas le plus courant d'utilisation de fonction d nie ailleurs est l'utilisation des fonctions e de la biblioth que standard. Avant d'utiliser une fonction de la biblioth que standard, il e e faudra donc la d clarer en fonction externe. Il y a une m thode permettant de faire cela e e de mani re automatique gr^ce au m canisme d'inclusion de source du pr processeur. Cela e a e e est expliqu dans la documentation de chaque fonction. e

1.15.7 Comprendre la documentation de la biblioth que standard e

Dans la documentation concernant les fonctions de la biblioth que standard, que ce e soit dans la norme ou dans les manuels unix, l'information concernant l'interface d'appel de la fonction se trouve dans le paragraphe Synopsis. Dans ces paragraphes, se trouve toujours une commande d'inclusion de source. Exemple de la fonction cosinus :

Synopsis 

include math.h double cosdouble x;

Il faut comprendre que le chier math.h contient un ensemble de d nitions n cessaires e e a l'utilisation de cos, en particulier la d claration de cos en fonction externe, savoir : e a
extern double cosdouble x;

Il faut donc inclure le chier math.h avant toute utilisation de la fonction cos.

1.15.8 Les fonctions dans le style K&R

La d nition des fonctions est la plus importante di rence entre ansi et k&r. Dans la e e version k&r du langage, le prototype c'est dire la liste-de-d clarations-de-param tres a e e est remplac par une liste d'identi cateurs, qui sont les noms des param tres. La d clarae e e tion des types des param tres se fait juste apr s, de la mani re suivante : e e e
int sum_squarei,j int i, int j; int resultat; resultat = i*i + j*j; returnresultat; * * liste des noms des param tres formels e d claration du type des param tres e e * *

26

En ce qui concerne la d claration de fonction externe, il faut pr xer avec le mot-cl e e e extern, l'en-t^te de la fonction d barrass e de la liste des noms des param tres, comme e e e e ceci :
extern int sum_square;

Dans ce cas, le compilateur ne conna^t pas le type des param tres de la fonction, il lui
e est donc impossible de d tecter une erreur portant sur le type des param tres lors d'un e e appel de fonction externe. Cette situation est assez catastrophique et c'est la raison pour laquelle le comit de normalisation a introduit le concept de prototype de fonction vu au e chapitre 1.15.1. Il n'a cependant pas voulu faire un changement incompatible, il a donc d cid que les deux m thodes taient accept es, en pr cisant toutefois que la m thode e e e e e e e k&r tait une caract ristique obsolescente. En clair, cela signi e que cette m thode sera e e e abandonn e dans la prochaine r vision de la norme, si prochaine r vision il y a. e e e

Remarque
Nous ne pouvons que conseiller l'utilisation exclusive des prototypes de fonctions, et de ne jamais utiliser la m thode k&r. Si nous avons expos celle-ci, c'est pour permettre e e au lecteur de comprendre les quantit s normes de source C existant, qui sont crites a la e e e k&r.

1.16 Impression formatt e e
Pour faire des entr es-sorties, il est n cessaire de faire appel aux possibilit s de la e e e biblioth que standard. Celle-ci comporte une proc dure permettant de r aliser des sorties e e e formatt es : il s'agit de printf. On l'appelle de la mani re suivante : e e printf  cha^ne-de-caract res , liste-d'expressions  ;
e cha^ne-de-caract res est le texte imprimer dans lequel on peut librement mettre des
e a s quences d' chappement qui indiquent le format selon lequel on veut imprimer la valeur e e des expressions se trouvant dans liste-d'expressions . Ces s quences d' chappement sont e e compos e du caract re  suivi d'un caract re qui indique le format d'impression. Il existe e e e entre autres, c pour un caract re, d pour un entier imprimer en d cimal, x pour un e a e entier imprimer en hexad cimal. Exemple : a e
int i = 12; int j = 32; printf"la valeur de i est d et celle de j est d",i,j;

imprimera :
la valeur de i est 12 et celle de j est 32

Il est possible d'avoir une liste-d'expressions vide, dans ce cas l'appel a printf devient : printf  cha^ne-de-caract res  ;
e par exemple, pour imprimer le mot erreur en le soulignant 6, on peut crire : e
printf"erreur b b b b b b______"; * b est back-space *

6. a condition que la sortie se fasse sur un terminal papier

27

Fichier d'include
La d claration de printf en tant que fonction externe se trouve dans le chier stdio.h e qu'il faudra inclure avant toute utilisation. En t^te du programme il faudra donc mettre : e 
include stdio.h

1.17 Structure d'un programme
Nous ne consid rerons pour d buter que le cas de programmes form s d'une seule unit e e e e de compilation. Un programme C est une suite de d clarations de variables et de d nitions e e de fonctions dans un ordre quelconque. Les variables sont des variables dont la dur e de e vie est gale celle du programme, et qui sont accessibles par toutes les fonctions. Ces e a variables sont dites variables globales, par opposition aux variables d clar es l'int rieur e e a e des fonctions qui sont dites locales. Bien que ce ne soit pas obligatoire, il est g n ralement consid r comme tant un bon ee ee e style de programmation de regrouper toutes les d clarations de variables en t^te du proe e gramme. La structure d'un programme devient alors la suivante :
programme :  liste-de-d clarations option e liste-de-d nitions-de-fonctions e

Il peut n'y avoir aucune d claration de variable, mais il doit y avoir au moins la d nie e tion d'une proc dure dont le nom soit main, car pour lancer un programme C, le syst me e e appelle la proc dure de nom main. Exemple : e
int i,j; double a,b,c; void p1int k * i,j,a,b,c sont des variables globales *

* * * * * * * * * * * *

d but de la d finition de la proc dure p1 e e e p1 a un seul param tre entier : k e variables locales p1 a instructions de p1 qui peuvent acc der e a k,i,j,a,b,c,s et t fin de la d finition de p1 e d but de la d finition de la fonction f1 e e f1 a deux param tres flottants: x et y e variables locales f1 a instructions de f1 qui peuvent acc der e a x,y,i,j,a,b,c,u et v fin de la d finition de f1 e

* * * * * * * * * * * *

int s,t; ... ...

int f1double x,double y

double u,v; ... ...

28

int main ...

* * *

d but du main, il n'a pas de param tre e e instructions qui appellerons p1 et f1 fin de la d finition de main e

* * *

1.18 Terminaison d'un programme
On peut r aliser la terminaison d'un programme en appelant la fonction exit qui e fait partie de la biblioth que standard. Cette fonction admet un param tre entier qui est e e un code indiquant le type de la terminaison : une valeur nulle indique que le programme s'est convenablement termin , toute valeur non nulle indique une terminaison avec erreur. e Cette valeur est transmise a l'environnement d'ex cution du programme 7 d'une mani re e e d pendante de l'impl mentation. e e Un retour de la fonction main est quivalent un appel la fonction exit en lui e a a passant en param tre la valeur retourn e par main. Si l'environnement d'ex cution teste e e e la valeur rendue par le programme, il faut donc terminer la fonction main par return0.

1.19 Mise en oeuvre du compilateur C sous UNIX
Le lecteur sera suppos ma^triser un diteur de textes lui permettant de cr er un chier e
e e contenant le source d'un programme. Supposons que le nom d'un tel chier soit essai1.c, pour en r aliser sous unix la compilation et l' dition de liens avec la biblioth que standard, e e e il faut mettre la commande : e
cc -o essai1 essai1.c

le binaire ex cutable se trouve alors dans le chier e d' mettre la commande : e
essai1

essai1.

Pour l'ex cuter, il su t e

Pour v ri er qu'il n'y a pas de probl me pour la mise en uvre du compilateur, on peut e e essayer sur un des plus petits programmes possibles, savoir un programme sans variables a globales, et n'ayant qu'une seule proc dure qui sera la proc dure main. Exemple : e e 
include stdio.h int main printf"a marche!! n"; c

Ecrire un programme comportant : 1. la d claration de 3 variables globales enti res heures, minutes, secondes ; e e
7. Sous unix ce sera le shell de l'utilisateur

1.20 Exercice

29

2. une proc dure print_heure qui imprimera le message : e
Il est ... heures ... minutes ... secondes

en respectant l'orthographe du singulier et du pluriel; 3. une proc dure set_heure qui admettra trois param tres de type entiers h, m, s, e e dont elle a ectera les valeurs respectivement a heures, minutes et secondes ; 4. une proc dure tick qui incr mentera l'heure de une seconde ; e e 5. la proc dure main sera un jeu d'essai des proc dures pr c dentes ; e e ee Une solution possible est donn e ci-apr s. e e

30 

include stdio.h int heures, minutes, secondes; ***************************************************************************** * * * print_heure * * * * But: * * Imprime l'heure * * * * Interface: * * Utilise les variables globales heures, minutes, secondes * * * ***************************************************************************** void print_heure printf"Il est d heure",heures; if heures 1 printf"s"; printf" d minute",minutes; if minutes 1 printf"s"; printf" d seconde",secondes; if secondes 1 printf"s"; printf" n";

***************************************************************************** * * * set_heure * * * * But: * * Met l'heure une certaine valeur a * * * * Interface: * * h, m, s sont les valeurs donner heures, minutes, secondes a a * * * ***************************************************************************** void set_heureint h, int m, int s heures = h; minutes = m; secondes = s;

***************************************************************************** * * * tick * * * * But: * * Incr mente l'heure de une seconde e * * * * Interface: * * Utilise les variables globales heures, minutes, secondes * * * ***************************************************************************** void tick

31

secondes = secondes + 1; if secondes = 60 secondes = 0; minutes = minutes + 1; if minutes = 60 minutes = 0; heures = heures + 1; if heures = 24 heures = 0;

***************************************************************************** * * * main * * * ***************************************************************************** int main set_heure3,32,10; tick; print_heure; set_heure1,32,59; tick; print_heure; set_heure3,59,59; tick; print_heure; set_heure23,59,59; tick; print_heure;

32

1.21 R cr ation e e
Ami lecteur, si vous m'avez suivi jusqu'au bout de ce chapitre indigeste, vous m ritez e un divertissement. Tous les ans, est organis sur Internet le concours international du code C le plus obscur e International Obfuscated C Code Competition, ioccc en abr g . Le but est de produire ee un programme qui se compile et s'ex cute sans erreur, dont le source est volontairement e le plus obscur possible ce qui est facile, mais qui est  int ressant  un titre ou un e a a autre. C'est sur ce dernier point que doit s'exercer la cr ativit des participants. Tous les e e ans, les meilleures contributions sont de v ritables joyaux et sont librement accessibles via e l'url : ftp: ftp.uu.net pub ioccc. Nous pr sentons ci-dessous la contribution de Brian Westley pour l'ann e 1990. Son e e programme a ceci d'extraordinaire que le source C peut se lire comme un texte en  anglais  : il s'agit d'une conversation pistolaire entre un amoureux et sa belle r tive, h las e e e pour lui. Il y a quelques petites licences prises par rapport du vrai anglais : 1s est a pris comme une approximation du mot anglais is, 1l est pris comme approximation de ll dans I'll get a break et des signes cabalistiques sont introduits entre les mots, mais c'est parfaitement lisible. Il y a aussi un probl me avec le langage C : le compilateur utilis en 1990 par B. Westley e e n' tait pas ansi et acceptait le su xe s derri re une constante enti re pour lui donner le e e e type short int. Si on transforme les 1s en 1, le programme se compile et s'ex cute sans e erreur. L'ex cutable est un programme ... d'e euillage de la marguerite ! Il faut lui passer e en param tre un nombre sens ^tre le nombre de p tales de la marguerite, et le programme e ee e va  dire  : love me, love me not, love me, love me not etc. 8 un nombre de fois gal au e nombre de p tales. Voici le texte du programme : e
char*lie; double time, me= !0XFACE, not; int rested, get, out; mainly, die char ly, **die ; signed char lotte, dear; charlotte--; forget= !me;; not 1 - out & out ;lie; char lotte, my= dear, **let= !!me *!not+ ++die; char*lie=

8. Les anglais semblent avoir une conception binaire du sentiment amoureux

33

"The gloves are OFF this time, I detest you, snot n 0sed GEEK!"; do not= *lie++ & 0xF00L* !me; define love char*lie love 1s *!not= atoilet get -me? charlottecharlotte: my- *love 'I' - *love - 'U' 'I' - long - 4 - 'U' - !! time =out= 'a'; while my - dear && 'I'-1l -get- 'a'; break; char*lie++; char*lie++, char*lie++; hell:0, char*lie; get *out* shortly -0-'R'- get- 'a'^rested; do auto*eroticism, that; puts* out - 'c' -'P'-'S' +die+ -2 ; while!"you're at it"; for *char*&lotte^= charlotte; love ly char++lotte+ !!0xBABE ; if 'I' -lie 2 +charlotte  'I'-1l ***die; else if 'I' * get *out* 'I'-1l **die 2  *char*&lotte -= '4' - 'I'-1l; not; forget=! get; !out; char*lie charlotte; & 0xD0- !not return!! 

charlotte; do not* putcharlie out *!not* !!me +charlotte ; not; for;!'a';; while love char*lie; register this; switch charlie charlotte -1s *!out char*les, get= 0xFF, my; case' ': *char*&lotte += 15; !not +char*lie*'s'; this +1s+ not; default: 0xF +char*lie; get - !out; if not-- goto hell; exit charlotte;

34

Chapitre 2

Les tableaux
Dans ce chapitre nous allons voir comment d clarer un tableau, comment l'initialiser, e comment faire r f rence un des ses l ments. Du point de vue algorithmique, quand on ee a ee utilise des tableaux, on a besoin d'intructions it ratives, nous passerons donc en revue e l'ensemble des instructions it ratives du langage. Nous terminerons par un certain nombre e d'op rateurs tr s utiles pour mettre en uvre ces instructions. e e

2.1 Les tableaux

2.1.1 D claration de tableaux dont les l ments ont un type de base e ee
Pour d clarer un tableau dont les l ments ont un type de base : e ee partir de la d claration de variable ayant un type de base ; e ajouter entre crochets le nombre d' l ments du tableau apr s le nom. ee e Exemple :
int t 10 ; long int t1 10 , t2 20 ; * * t tableau de 10 int t1 tableau de 10 long int, t2 tableau de 20 long int

* *

En pratique, il est recommand de toujours donner un nom a la constante qui indique le e nombre d' l ments d'un tableau. Exemple : ee 
define N 100 int t N ;

Les points importants sont les suivants : les index des l ments d'un tableau vont de 0 N - 1 ; ee a la taille d'un tableau doit ^tre connue statiquement par le compilateur. e Impossible donc d' crire : e
int t n ;

o n serait une variable. u 35

Il est possible d'initialiser un tableau avec une liste d'expressions constantes s par es e e par des virgules, et entour e des signes et . Exemple : e 
define N 5 int t N = 1, 2, 3, 4, 5 ;

2.1.2 Initialisation d'un tableau

On peut donner moins d'expressions constantes que le tableau ne comporte d' l ments. ee Dans ce cas, les premiers l ments du tableau seront initialis s avec les valeurs indiqu es, ee e e les autres seront initialis s a z ro. Exemple : e e 
define N 10 int t N = 1, 2 ;

Les l ments d'indice 0 et 1 seront initialis s respectivement avec les valeurs 1 et 2, les ee e autres l ments seront initialis s z ro. ee e a e Il n'existe malheureusement pas de facteur de r p tition, permettant d'exprimer  iniee tialiser n l ments avec la m^me valeur v . Il faut soit mettre n fois la valeur v dans ee e l'initialisateur, soit initialiser le tableau par des instructions.

Cas particulier des tableaux de caract res e

Un tableau de caract res peut ^tre initialis par une liste de constantes caract res. e e e e Exemple :
char ch 3 = 'a', 'b', 'c' ;

C'est videmment une m thode tr s lourde. e e e Un tableau de caract res peut ^tre initialis par une cha^ne litt rale. Exemple : e e e
e
char ch 8 = "exemple";

On se rappelle que le compilateur compl te toute cha^ne litt rale avec un caract re e
e e null, il faut donc que le tableau ait au moins un l ment de plus que le nombre de ee caract res de la cha^ne litt rale. e
e Il est admissible que la taille d clar e pour le tableau soit sup rieure la taille de la e e e a cha^ne litt rale. Exemple :
e
char ch 100 = "exemple";

dans ce cas, seuls les 8 premiers caract res de ch seront initialis s. e e Il est galement possible de ne pas indiquer la taille du tableau et dans ce cas, le e compilateur a le bon go^t de compter le nombre de caract res de la cha^ne litt rale u e
e et de donner la taille ad quate au tableau sans oublier le null. Exemple : e
char ch = "ch aura 22 caract res"; e

36

Il est galement possible de donner au tableau une taille gale au nombre de carace e t res de la cha^ne. Dans ce cas, le compilateur comprend qu'il ne faut pas rajouter e
le null de la n de cha^ne. Exemple :

char ville 8 = "bordeaux";

2.1.3 R f rence un l ment d'un tableau ee a ee
Syntaxe : Dans sa forme la plus simple, une r f rence un l ment de tableau a la syntaxe ee a ee suivante :
expression :  nom-de-tableau expression 1

S mantique : expression 1 doit d livrer une valeur enti re, et l'expression d livre l' l e e e e ee ment d'indice expression 1 du tableau. Une telle expression est une lvalue, on peut donc la rencontrer aussi bien en partie gauche qu'en partie droite d'a ectation. Par exemple, dans le contexte de la d claration : e 
define N 10 int t N ;

on peut crire : e
x = t i ; t i+j = k; * * r f rence l' l ment d'indice i du tableau t e e a e e affectation de l' l ment d'indice i+j du tableau t e e * *

2.1.4 Cha^nes et tableaux de caract res
e
Le langage C fait la distinction entre tableau de caract res et cha^ne de caract res : une e
e cha^ne de caract res est un tableau de caract res dont la n est indiqu e par un caract re
e e e e null. C'est une convention tr s pratique exploit e par la biblioth que standard. e e e

2.2 Les instructions it ratives e
2.2.1 Instruction for
Syntaxe : instruction : 

for 

expression 1 option instruction

;

expression 2 option

;

expression 3 option 

S mantique : l'ex cution r alis e correspond l'organigramme suivant : e e e e a 37

expression1

? ? ? ?

-

expression2 != 0? oui instruction expression3

non n du for

Lorsque l'on omet expression1 et ou expression2 et ou expression3 , la s mantique est e celle de l'organigramme pr c dent, auquel on a enlev la ou les parties correspondantes. ee e

Remarques
On voit que la vocation de expression 1 et expression 3 est de r aliser des e ets de bord, e puisque leur valeur est inutilis e. Leur fonction logique est d'^tre respectivement les parties e e initialisation et it ration de la boucle. L' expression 2 est utilis e pour le test de bouclage. e e L'instruction est le travail de la boucle.

Exemple de boucle for
Initialisation d'un tableau a z ro : e 
define N 10 int t N ; for i = 0; i N; i = i + 1 t i = 0;

2.2.2 Instruction while
Syntaxe : instruction : 

while 

expression 

instruction

S mantique : e l'ex cution r alis e correspond a l'organigramme suivant : e e e 38

-

expression != 0? oui instruction

? ?

non n du while

2.2.3 Instruction do
Syntaxe : instruction : 

do

instruction

while 

expression 

;

S mantique : e l'ex cution r alis e correspond a l'organigramme suivant : e e e

-


2.2.4 Instruction break
Syntaxe : instruction :

instruction

? ?

expression != 0? oui

non n du do 

break ;

S mantique : e Provoque l'arr^t de la premi re instruction for, while, do englobante. e e 39

Exemple
L'instruction for ci-dessous est stopp e au premier i tel que t e
for i = 0; i N; i = i + 1 if t i == 0 break; i

est nul :

2.2.5 Instruction continue
Syntaxe : instruction : 

continue ;

S mantique : e Dans une instruction for, while ou do, l'instruction continue provoque l'arr^t de e l'it ration courante, et le passage au d but de l'it ration suivante. e e e

Exemple
Supposons que l'on parcoure un tableau t pour r aliser un certain traitement sur tous e les l ments, sauf ceux qui sont n gatifs : ee e
for i = 0; i if t i ... N; i = i + 1 0  continue; * * on passe au i suivant dans le for traitement de l' l ment courant e e * *

2.3 Les op rateurs e

Le langage C o re un op rateur d'incr mentation qui peut ^tre utilis soit de mani re e e e e e pr x , soit de mani re post x . Cet op rateur se note ++ et s'applique une lvalue. Sa e e e e e a syntaxe d'utilisation est donc au choix, soit ++ lvalue utilisation en pr x , soit lvalue ++ e e utilisation en post x . Tout comme l'op rateur d'a ectation, l'op rateur d'incr mentae e e e tion r alise a la fois un e et de bord et d livre une valeur : e e ++ lvalue incr mente lvalue de 1 et d livre cette nouvelle valeur. e e lvalue ++ incr mente lvalue de 1 et d livre la valeur initiale de lvalue. e e

2.3.1 Op rateur pr et postincr ment e e e

Exemples
Soient i un int et t un tableau de int :
i = 0; t i++ = 0; t i++ = 0; i = 1; * * met z ro l' l ment d'indice 0 a e e e met z ro l' l ment d'indice 1 a e e e * *

40

t ++i t ++i

= 0; = 0;

* *

met z ro l' l ment d'indice 2 a e e e met z ro l' l ment d'indice 3 a e e e

* *

2.3.2 Op rateur pr et postd cr ment e e e e

Il existe galement un op rateur de d cr mentation qui partage avec l'op rateur incr e e e e e e ment les caract ristiques suivantes : e il peut s'utiliser en pr xe ou en post x ; e e il s'applique une lvalue, ; a il fait un e et de bord et d livre une valeur. e Cet op rateur se note -- et d cr mente la lvalue de 1 : e e e -- lvalue d cr mente lvalue de 1 et d livre cette nouvelle valeur. e e e lvalue -- d cr mente lvalue de 1 et d livre la valeur initiale de lvalue. e e e

Exemples

Soient i un int et t un tableau de int :
i = 9; t i-- = 0; t i-- = 0; i = 8; t --i = 0; t --i = 0; * * met z ro l' l ment d'indice 9 a e e e met z ro l' l ment d'indice 8 a e e e * *

* *

met z ro l' l ment d'indice 7 a e e e met z ro l' l ment d'indice 6 a e e e

* *

2.3.3 Quelques utilisations typiques de ces op rateurs e
Utilisation dans les instructions expression
On a vu qu'une des formes d'instruction possibles en C est : expression ; et que cela n'a de sens que si l'expression r alise un e et de bord. Les op rateurs ++ e e et -- r alisant pr cis ment un e et de bord, permettent donc d' crire des instructions e e e e se r duisant une expression utilisant un de ces op rateurs. Une incr mentation ou une e a e e d cr mentation de variable se fait classiquement en C de la mani re suivante : e e e
i++; j--; * * incr mentation de i e d cr mentation de j e e * *

Utilisation dans les instructions it ratives e
for i = 0; i ... N; i++

Une boucle for de parcours de tableau s' crit typiquement de la mani re suivante : e e

41

2.3.4 Op rateur et logique e
Syntaxe : expression : 

expression 1

&&

expression 2

S mantique : e expression1 est valu e et : e e 1. si sa valeur est nulle, l'expression && rend la valeur 0 ; 2. si sa valeur est non nulle, expression2 est valu e, et l'expression e e valeur 0 si expression2 est nulle, et 1 sinon.
&&

rend la

On voit donc que l'op rateur && r alise le et logique de expression 1 et expression 2 en e e prenant pour faux la valeur 0, et pour vrai toute valeur di rente de 0. e

Remarque sur la s mantique e
On a la certitude que expression 2 ne sera pas valu e si expression 1 rend la valeur e e faux. Ceci pr sente un int r^t dans certains cas de parcours de tableau ou de liste de blocs e ee cha^n s. Par exemple dans le cas d'un parcours de tableau la recherche d'un l ment ayant
e a ee une valeur particuli re, supposons que l'on utilise comme test de n de boucle l'expression e
i n && t i != 234 

on boucle tant que ce test est vrai, o i n est le test permettant de ne pas d border u e du tableau, et t i != 234 est le test de l' l ment recherch . S'il n'existe dans le tableau ee e aucun l ment gal 234, il va arriver un moment o on va valuer i n && t i != 234 ee e a u e avec i = n. La s mantique de l'op rateur && assurant que l'expression t i != 234 ne e e sera pas valu e, on ne court donc pas le risque d'avoir une erreur mat rielle t n peut e e e r f rencer une adresse m moire invalide. ee e

Exemples d'utilisation
int a,b; if a 32 && b if  a && b 1 b = a 32 && b 64 ... ... 64;

2.3.5 Op rateur ou logique e
Syntaxe : expression : 

expression 1

||

expression 2

S mantique : e expression 1 est valu e et : e e si sa valeur est non nulle, l'expression || d livre la valeur 1 ; e 42

sinon, expression 2 est valu e, si sa valeur est nulle, l'expression || d livre la e e e valeur 0 sinon elle d livre la valeur 1. e On voit donc que l'op rateur || r alise le ou logique de ses op randes, toujours avec e e e les m^mes conventions pour les valeurs vrai et faux, savoir 0 pour faux, et n'importe e a quelle valeur non nulle pour vrai. Dans ce cas galement, on a la certitude que le second e op rande ne sera pas valu si le premier d livre la valeur vrai. e e e e

Exemples
int a,b; if a 32 || b if  a || b 1 b = a 32 || b 64 ... ... 64;

2.3.6 Op rateur non logique e
Syntaxe : expression : 

!

expression

S mantique : e expression est valu e, si sa valeur est nulle, l'op rateur ! d livre la valeur 1, sinon e e e e il d livre la valeur 0. e Cet op rateur r alise le non logique de son op rande. e e e

2.4 Exercice
D clarer un tableau nb_jour qui doit ^tre initialis de faon ce que nb_jour i soit e e e c a gal au nombre de jours du ieme mois de l'ann e pour i allant de 1 12 nb_jour 0 sera e e a inutilis . e Ecrire une proc dure d'initialisation de nb_jour qui utilisera l'algorithme suivant : e si i vaut 2 le nombre de jours est 28 ; sinon si i pair et i = 7 ou i impair et i 7 le nombre de jours est 30 ; sinon le nombre de jours est 31. Ecrire une proc dure d'impression des 12 valeurs utiles de nb_jour. La proc dure main e e se contentera d'appeler les proc dures d'initialisation et d'impression de nb_jour. e

43 

include stdio.h int nb_jours 13 ; ***************************************************************************** * * * init_nb_jours * * * * But: * * Initialise le tableau nb_jours * * * ***************************************************************************** void init_nb_jours int i; for i = 1; i = 12; i++ if i == 2 nb_jours 2 = 28; else if  i  2 == 0 && i nb_jours i = 30; else nb_jours i = 31;

= 7 || i  2 == 1 && i

7 

***************************************************************************** * * * print_nb_jours * * * * But: * * Imprime le contenu du tableau nb_jours * * * ***************************************************************************** void print_nb_jours int i; for i = 1; i printf"d printf" n"; = 12; i++ ",nb_jours i ;

***************************************************************************** * * * main * * * ***************************************************************************** int main init_nb_jours; print_nb_jours;

44

Chapitre 3

Les pointeurs
3.1 Notion de pointeur
Une valeur de type pointeur rep re une variable. En pratique, cela signi e qu'une valeur e de type pointeur est l'adresse d'une variable. variable de type pointeur vers un int

int

-

372

3.2 D clarations de variables de type pointeur vers les types e de base
Pour d clarer une variable pointeur vers un type de base : e partir de la d claration d'une variable ayant un type de base ; e ajouter le signe * devant le nom de la variable. Exemple :
int *pi; short int *psi; double *pd; char *pc; * * * * pi est un pointeur vers un int psi est un pointeur vers un short int pd pointeur vers un flottant double pr cision e pc pointeur vers un char * * * *

3.3 Type de pointeur g n rique e e
Le type void * est le type pointeur g n rique, c'est dire capable de pointer vers n'imee a porte quel type d'objet. Sans un tel type, il ne serait pas possible par exemple d'indiquer 45

le type d'objet rendu par les fonctions d'allocation de m moire qui rendent un pointeur e vers l'objet allou , puisque ce type varie d'une invocation a l'autre de la fonction. e Par exemple, la fonction malloc de la biblioth que standard est d nie de la mani re e e e 1 suivante : void *mallocsize t size;

Note
La solution quand on utilisait les compilateurs K&R tait d'utiliser le type char * qui e jouait de mani re conventionnelle ce r^le de pointeur g n rique. Le lecteur ne s' tonnera e o ee e donc pas de trouver dans les vieux ? manuels, la fonction malloc d nie de la mani re e e suivante :
char *mallocsize;

3.4 Op rateur adresse de e
L'op rateur & appliqu une variable d livre l'adresse de celle-ci ; cette adresse pourra e ea e ^tre a ect e une variable de type pointeur. On peut crire par exemple : e e a e
int i; int *pi; pi = &i; * * pi pointeur vers un int * *

le pointeur pi rep re la variable i e

3.5 Op rateur d'indirection e
Lorsque l'op rateur * est utilis en op rateur pr x , il agit de l'op rateur indirection e e e e e e qui, appliqu a une valeur de type pointeur, d livre la valeur point e. On peut crire par e e e e exemple :
int i; int *pi; pi = &i; *pi = 2; j = *pi + 1; * * * initialisation du pointeur pi initialisation de la valeur point e par pi e une utilisation de la valeur point e par pi e * * *

Remarque
L'op rateur * est surcharg : il peut ^tre op rateur de multiplication ou op rateur e e e e e d'indirection. La grammaire l ve l'ambigu
t car l'op rateur d'indirection est pr x , alors e e e e e que l'op rateur de multiplication est in x . Surcharger les op rateurs g^ne la lisibilit des e e e e e programmes. Exemple : si i et j sont des pointeurs vers des entier, la multiplication des deux valeurs point es s' crit : *i**j e e
1. size t est un type d ni dans stddef.h e

46

Devinette
Si i et j sont des pointeurs vers des entiers, *i**j est le produit des valeurs point es, e mais *i *j est-il le quotient des valeurs point es? R ponse a la n de ce chapitre. e e

3.6 Exercice
1. 2. 3. 4. 5. D clarer un entier i et un pointeur p vers un entier ; e Initialiser l'entier a une valeur arbitraire et faire pointer p vers i ; Imprimer la valeur de i ; Modi er l'entier point par p en utilisant p, pas i ; e Imprimer la valeur de i.

Une solution possible est donn e page suivante. e

47 

include

stdio.h

***************************************************************************** * * * main * * * ***************************************************************************** int main int i; int *p; i = 1; p = &i; printf"valeur de i avant: d n",i; *p = 2; printf"valeur de i apr s: d n",i; e

48

3.7 Pointeurs et op rateurs additifs e
3.7.1 Op rateurs + et e
L'op rateur + permet de r aliser la somme de deux valeurs arithm tiques, mais il e e e permet galement de r aliser la somme d'un pointeur et d'un entier. Une telle op ration e e e n'a de sens cependant, que si le pointeur rep re un l ment d'un tableau. e ee Soient p une valeur pointeur vers des objets de type T et un tableau dont les l ments ee sont du m^me type T ; si p rep re l' l ment d'indice i du tableau, p + j est une valeur e e ee de type pointeur vers T, qui rep re l' l ment d'indice i + j du tableau en supposant e ee qu'il existe. Il en va de m^me avec l'op rateur soustraction : si p rep re l' l ment d'indice i d'un e e e ee tableau, p - j rep re l' l ment d'indice i - j du tableau toujours en supposant qu'il existe. e ee Exemple : 
define N 10 int t N ; int *p,*q,*r,*s; p = &t 0 ; q = p + N-1; r = &t N-1 ; s = r - N-1; * * * * p rep re le premier l ment de t e e e q rep re le dernier l ment de t e e e r rep re le dernier l ment de t e e e s rep re le premier l ment de t e e e * * * *

La norme pr cise que pour r aliser la somme ou la di rence d'un pointeur et d'un e e e entier, il faut qu' la fois le pointeur et le r sultat rep rent les l ments d'un m^me tableau a e e ee e ou l' l ment  ctif apr s le dernier l ment du tableau. En d'autre termes, si on a : ee e ee 
define N 100 int t N ; int * p = &t 0 ;

L'expression p + N est valide, mais p - 1 ou p + N + 1 ne sont pas valides. La possibilit e de r f rencer l' l ment  ctif apr s le dernier l ment d'un tableau a t introduite pour ee ee e ee ee les probl mes de n de boucle de parcours de tableau mais on aurait pu s'en passer. e On peut appliquer les op rateurs ++ et -- des pointeurs et il est classique de les e a utiliser pour r aliser des parcours de tableaux. Exemple on rappelle que toute cha^ne est e
termin e par un null, c'est a dire le caract re ' 0' : e e
char mess char *p; = "Hello world!!";

3.7.2 Op rateurs ++ et -e

for p = &mess 0 ; *p != ' 0'; p++ * ici p rep re l' l ment courant de mess e e e *

49

Autre classique, en reprenant les variables mess et p de l'exemple pr c dent : ee
p = &mess 0 ; while *p != ' 0' * ici utilisation de *p++ *

3.8 Di rence de deux pointeurs e
Il est possible d'utiliser l'op rateur de soustraction pour calculer la di rence de deux e e pointeurs. Cela n'a de sens que si les deux pointeurs rep rent des l ments d'un m^me e ee e tableau. Soient p1 et p2 deux pointeurs du m^me type tels que p1 rep re le ieme l ment d'un e e ee eme l ment du m^me tableau, p2 - p1 est une valeur de type tableau, et p2 rep re le j e e e e ptrdiff_t qui est gale j - i. Le type ptrdiff_t est d ni dans le chier d'include e a e stddef.h En pratique, une variable de type ptrdiff_t pourra ^tre utilis e comme une e e variable de type int. La norme pr cise qu'il est valide de calculer la di rence de deux e e pointeurs condition que tous deux rep rent des l ments d'un m^me tableau, ou l' l ment a e ee e ee  ctif apr s le dernier l ment du tableau. e ee

3.9 Exercice
D clarer et initialiser statiquement un tableau d'entiers t avec des valeurs dont cere taines seront nulles. Ecrire une proc dure qui parcoure le tableau t et qui imprime les e index des l ments nuls du tableau, sans utiliser aucune variable de type entier. ee Une solution possible est donn e page suivante. e

50 

include

stdio.h 

define N 10 int t N = 1,2,0,11,0,12,13,14,0,4 ; ***************************************************************************** * * * print1 * * Premiere version * * * ***************************************************************************** void print1 int *pdeb,*pfin,*p; pdeb = &t 0 ; pfin = &t N-1 ; * * rep re le premier l ment de t e e e rep re le dernier l ment de t e e e * *

for p = pdeb; p = pfin; p++ if *p == 0 printf"d ",p - pdeb; printf" n";

***************************************************************************** * * * print2 * * Une autre version * * * ***************************************************************************** void print2 int *pdeb,*pfin,*p; pdeb = &t 0 ; pfin = pdeb + N; * rep re le premier l ment de t e e e * * rep re l' l ment fictif apres le dernier l ment de t * e e e e e

for p = pdeb; p pfin; p++ if *p == 0 printf"d ",p - pdeb; printf" n";

***************************************************************************** * * * main * * * ***************************************************************************** int main print1; print2;

51

3.10 Passage de param tres e

3.10.1 Les besoins du programmeur
En ce qui concerne le passage de param tres une proc dure, le programmeur a deux e a e besoins fondamentaux : soit il d sire passer une valeur qui sera exploit e par l'algorithme de la proc dure e e e c'est ce dont on a besoin quand on crit par exemple sinx. Une telle faon de e c passer un param tre s'appelle du passage par valeur ; e soit il d sire passer une r f rence une variable, de mani re a permettre la proc e ee a e a e dure de modi er la valeur de cette variable. C'est ce dont on a besoin quand on crit e une proc dure r alisant le produit de deux matrices prodmata,b,c o l'on veut e e u qu'en n d'ex cution de prodmat, la matrice c soit gale au produit matriciel des e e matrices a et b. prodmat a besoin des valeurs des matrices a et b, et d'une r f rence ee vers la matrice c. Une telle faon de passer un param tre s'appelle du passage par c e adresse.

3.10.2 Comment les langages de programmation satisfont ces besoins
Face ces besoins, les concepteurs de langages de programmation ont imagin di a e e rentes mani res de les satisfaire, et quasiment chaque langage de programmation dispose e de sa strat gie propre de passage de param tres. e e Une premi re possibilit consiste arguer du fait que le passage de param tre par e e a e adresse est plus puissant que le passage par valeur, et r aliser tout passage de a e param tre par adresse c'est la strat gie de fortran et pl 1 ; e e Une seconde possibilit consiste a permettre au programmeur de d clarer explicitee e ment quels param tres il d sire passer par valeur et quels param tres il d sire passer e e e e par adresse c'est la strat gie de pascal ; e La derni re possibilit consistant r aliser tout passage de param tre par valeur e e a e e semble irr aliste puisqu'elle ne permet pas de satisfaire le besoin de modi cation e d'un param tre. C'est cependant la strat gie choisie par les concepteurs du langage e e C.

3.10.3 La strat gie du langage C e
En C, tout param tre est pass par valeur, et cette r gle ne sou re aucune excepe e e tion. Cela pose le probl me de r aliser un passage de param tre par adresse lorsque le e e e programmeur en a besoin. La solution a ce probl me consiste dans ce cas, a d clarer le pa e e ram tre comme tant un pointeur. Cette solution n'est rendue possible que par l'existence e e de l'op rateur adresse de qui permet de d livrer l'adresse d'une lvalue. e e Voyons sur un exemple. Supposons que nous d sirions crire une proc dure add, ade e e mettant trois param tres a, b et c. Nous d sirons que le r sultat de l'ex cution de add e e e e soit d'a ecter au param tre c la somme des valeurs des deux premiers param tres. Le e e param tre c ne peut videmment pas ^tre pass par valeur, puisqu'on d sire modi er la e e e e e 52

valeur du param tre e ectif correspondant. Il faut donc programmer add de la mani re e e suivante :
void addint a, int b, int *c * c rep re l'entier o on veut mettre le r sultat e u e *

*c = a + b;

int main int i,j,k; * on passe les valeurs de i et j comme premiers param tres e * on passe l'adresse de k comme troisi me param tre e e addi,j,&k; * *

3.11 Discussion
1. Nous estimons qu'il est int ressant pour le programmeur de raisonner en terme de e passage par valeur et de passage par adresse et qu'il est pr f rable d'a rmer, lorsque ee l'on crit f&i;  i est pass par adresse f , plut^t que d'a rmer  l'adresse de e e a o i est pass e par valeur f  , tout en sachant que c'est la deuxi me a rmation qui e a  e colle le mieux la stricte r alit du langage. Que l'on ne s' tonne donc pas dans la a e e e suite de ce manuel de nous entendre parler de passage par adresse. 2. Nous retiendrons qu'en C, le passage de param tre par adresse est enti rement g r e e ee par le programmeur. C'est la charge du programmeur de d clarer le param tre a e e concern comme tant de type pointeur vers ... et de bien songer, lors de l'appel de e e la fonction, passer l'adresse du param tre e ectif. a e

3.12 Une derni re pr cision e e
Quand un langage o re le passage de param tre par valeur, il y a deux possibilit s : e e 1. soit le param tre est une constante donc non modi able e 2. soit le param tre est une variable locale la proc dure. Cette variable est initialis e e a e e lors de l'appel de la proc dure avec la valeur du param tre e ectif. e e C'est la seconde solution qui a t retenue par les concepteurs du langage C. Voyons sur un ee exemple. Supposons que l'on d sire crire une fonction sum admettant comme param tre n e e e et qui rende la somme des n premiers entiers. On peut programmer de la mani re suivante : e

53

int sumint n int r = 0; for  ; n returnr; 0; n-- r = r + n;

On voit que le param tre n est utilis comme variable locale, et que dans l'instruction for, e e la partie initialisation est vide puisque n est initialis e par l'appel de sum. e

3.13 Exercice
On va coder un algorithme de cryptage tr s simple : on choisit un d calage par exemple e e 5, et un a sera remplac par un f, un b par un g, un c par un h, etc. On ne cryptera que e les lettres majuscules et minuscules sans toucher ni a la ponctuation ni la mise en page a caract res blancs et line feed. On supposera que les codes des lettres se suivent de a a z e et de A Z. On demande de : a 1. d clarer un tableau de caract res mess initialis avec le message en clair ; e e e 2. crire une proc dure crypt de cryptage d'un caract re qui sera pass par adresse ; e e e e 3. crire le main qui activera crypt sur l'ensemble du message et imprimera le r sultat. e e

54 

include

stdio.h

char mess = "Les sanglots longs des violons de l'automne n blessent mon coeur d'une langeur monotone"; define DECALAGE 5 ***************************************************************************** * * * crypt * * * * But: * * Crypte le caract re pass en param tre e e e * * * * Interface: * * p : pointe le caract re crypter e a * * * ***************************************************************************** void cryptchar *p enum BAS, HAUT ; int casse; if *p = 'a' && *p = 'z' casse = BAS; else if *p = 'A' && *p = 'Z' casse = HAUT; else return; *p = *p + DECALAGE; if casse == BAS && *p

'z' || casse == HAUT && *p

'Z' *p = *p -26;

***************************************************************************** * * * main * * * ***************************************************************************** int main char *p; int i; * phase de cryptage p = &mess 0 ; while*p cryptp++; *

* impression du r sultat e printf"R sultat: n"; e printfmess; printf" n";

*

55

3.14 Lecture formatt e e
Il existe dans la biblioth que standard une fonction de lecture formatt e qui fonctionne e e selon le m^me principe que la proc dure printf. Sa syntaxe d'utilisation est la suivante : e e scanf  format , liste-d'expressions  ; format est une cha^ne de caract res indiquant sous forme de s quences d' chappement les
e e e entit s que scanf lit sur l'entr e standard : e e d pour un nombre d cimal ; e x pour un nombre crit en hexad cimal ; e e c pour un caract re. e Tous les l ments de la liste-d'expressions doivent d livrer apr s valuation l'adresse de ee e e e la variable dans laquelle on veut mettre la valeur lue. Si le ot de caract res lu sur e l'entr e standard ne correspond pas a format, scanf cesse d'a ecter les variables de listee d'expressions la premi re disparit . Exemple : a e e
scanf"d x",&i,&j;

cette instruction va lire un nombre crit en d cimal et mettre sa valeur dans la variable e e i, puis lire un nombre crit en hexad cimal et mettre sa valeur dans la variable j. On e e aura remarqu que les param tres i et j ont t s pass s par adresse scanf. Si l'entr e e e ee e a e standard commence par un nombre d cimal non suivi d'un nombre hexad cimal, seul i e e recevra une valeur. Si l'entr e standard ne commence pas par un nombre d cimal, ni i ni e e j ne recevront de valeur.

Valeur rendue Attention

Sur rencontre de n de chier, la fonction scanf rend EOF, sinon elle rend le nombre de variables qu'elle a pu a ecter. Une erreur facile a commettre est d'omettre les op rateurs & devant les param tres de e e scanf. C'est une erreur di cile a d tecter car le compilateur ne donnera aucun message e d'erreur et l'ex cution, ce sont les valeurs de i et j qui seront interpr t es comme des a e ee adresses par scanf. Avec un peu de chance ces valeurs seront des adresses invalides, et le programme s'avortera 2 sur l'ex cution du scanf, ce qui donnera une id e du probl me. e e e Avec un peu de malchance, ces valeurs donneront des adresses parfaitement acceptables, et le scanf s'ex cutera en allant craser les valeurs d'autres variables qui ne demandaient e e rien personne. Le programme pourra s'avorter beaucoup plus tard, rendant tr s di cile a e la d tection de l'erreur. e

3.15 Les derni res instructions e
Le langage C comporte 3 instructions que nous n'avons pas encore vu : un if g n ralis , ee e un goto et une instruction nulle.
2. Le terme avorter est prendre au sens technique de abort a

56

3.15.1 Instruction switch

Le langage C o re une instruction switch qui est un if g n ralis . ee e Syntaxe : instruction :  switch  expression 
case case .... case expression n : liste-d'instructionsn default : liste-d'instructions

expression 1 expression 2

: :

liste-d'instructions1 option liste-d'instructions2 option

break;option break;option

option

break;option

De plus : toutes les expression i doivent d livrer une valeur connue a la compilation ; e il ne doit pas y avoir deux expression i d livrant la m^me valeur ; e e l'alternative default est optionnelle. S mantique : e 1. expression est valu e, puis le r sultat est compar avec expression 1 , exprese e e e sion 2 , etc. 2. la premi re expression i dont la valeur est gale celle de expression, on a e e a ex cute la ou les 3 liste-d'instructions correspondantes jusqu' la rencontre e a de la premi re instruction break;. La rencontre d'une instruction break termine e l'ex cution de l'instruction switch. e 3. si il n'existe aucune expression i dont la valeur soit gale celle de expression, e a on ex cute la liste-d'instructions de l'alternative default si celle-ci existe, sinon e on ne fait rien. Vu le nombre de parties optionnelles dans la syntaxe, il y a 3 types d'utilisations possibles pour le switch. Premi re possibilit , on peut avoir dans chaque alternative une e e liste-d'instructions et un break; comme dans l'exemple suivant :

Discussion

3. la ou les, car dans chaque case, le break est optionnel

57

enum

BLEU=1, BLANC, ROUGE ;

void print_colorint color switchcolor case BLEU : printf"bleu"; break; case BLANC : printf"blanc"; break; case ROUGE : printf"rouge"; break; default : printf"erreur interne du logiciel num ro xx n"; e

Deuxi me possibilit , on peut avoir une ou plusieurs alternatives ne poss dant ni listee e e d'instructions, ni break;. Supposons que l'on d sire compter dans une suite de caract res, e e le nombre de caract res qui sont des chi res, et le nombre de caract res qui ne le sont pas. e e On peut utiliser le switch suivant :
switchc case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': nb_chiffres++; break; default: nb_non_chiffres++;

Troisi me possibilit , une alternative peut ne pas avoir de break comme dans l'exemple e e suivant :
enum POSSIBLE, IMPOSSIBLE ;

void print_casint cas switch cas case IMPOSSIBLE: printf"im"; case POSSIBLE: printf"possible n"; break; case default: printf"erreur interne du logiciel num ro xx n"; e

58

Une telle utilisation du switch pose un probl me de lisibilit , car l'exp rience montre e e e que l'absence du break; est tr s di cile voir. Il est donc recommand de mettre un e a e commentaire, par exemple de la faon suivante : c
case IMPOSSIBLE: printf"im"; * ATTENTION: pas de break; *

Remarque
Le mot-cl break est surcharg : nous avons vu au chapitre 2.2.4 que l'instruction break e e permettait de stopper l'ex cution d'une instruction it rative for, while, do. Il est utilis e e e ici de mani re compl tement di rente. e e e

3.15.2 Instruction goto
Syntaxe : instruction : 

goto

identi cateur

;

S mantique : e Toute instruction peut ^tre pr c d e d'un identi cateur suivi du signe :. Cet identi e eee cateur est appel tiquette. Une instruction goto identi cateur a pour e et de transee f rer le contr^le d'ex cution a l'instruction tiquet e par identi cateur. L'instruction e o e e e goto et l'instruction cible du goto doivent se trouver dans la m^me proc dure : le e e langage C est un langage a branchement locaux. Exemple :
etiq2: ... goto etiq1; ... etiq1: ... goto etiq2;

* * * * *

des instructions goto avant d finition de l' tiquette e e des instructions des instructions goto apr s d finition de l' tiquette e e e

* * * * *

3.15.3 Instruction nulle
Syntaxe : instruction : 

;

S mantique : e ne rien faire ! 59

Cette instruction ne rend que des services syntaxiques. Elle peut ^tre utile quand on e d sire mettre une tiquette la n d'une instruction compos e. Par exemple : e e a e
... fin: ;

Elle est galement utile pour mettre un corps nul certaines instructions it ratives. e a e En e et, cause des e ets de bord dans les expressions, on peut arriver parfois faire a a tout le travail dans les expressions de contr^le des instructions it ratives. Par exemple, on o e peut initialiser a z ro un tableau de la mani re suivante : e e
for i = 0; i N; t i++ = 0 ; * instruction nulle *

Attention
Cette instruction nulle peut parfois avoir des e ets d sastreux. Supposons que l'on e veuille crire la boucle : e
for i = 0; i t i = i; N; i++

si par m garde on met un ; la n de ligne du for, on obtient un programme parfaitement e a correct, qui s'ex cute sans broncher, mais ne fait absolument pas ce qui tait pr vu. En e e e e et :
for i = 0; i t i = i; N; i++ ;

ex cute le for avec le seul e et d'amener la variable i la valeur N, et ensuite ex cute une e a e fois t i = i ce qui a probablement pour e et d' craser la variable d clar e juste apr s e e e e le tableau t.

3.16 Exercice
Ecrire une proc dure main se comportant comme une calculette c'est a dire ex cutant e e une boucle sur : 1. lecture d'une ligne suppos e contenir un entier, un op rateur et un entier ex : 12 + e e 34, les op rateurs seront + - *  ; e 2. calculer la valeur de l'expression ; 3. imprimer le r sultat. e 60

Commentaire de la solution

Nous faisons ici un commentaire sur la solution propos e qui se trouve la page e a suivante. Dans le cas o la ligne lue n'a pas une syntaxe correcte elle ne contient pas un u nombre, un signe, un nombre, le programme met un message d'erreur et ex cute exit1. e e Ceci ne r alise pas un interface utilisateur bien agr able, car il serait plus int ressant de e e e continuer la boucle au lieu de terminer le programme. Cela n'a pas t impl ment car ce ee e e n'est pas r alisable l'aide des seules possibilit s de base de scanf qui ont t pr sent es. e a e ee e e Dans le chapitre  Les entr es-sorties , scanf sera expliqu de mani re exhaustive et une e e e meilleure version de ce programme sera pr sent e. e e

61 

include enum

stdio.h

FAUX, VRAI ;

***************************************************************************** * * * main * * * ***************************************************************************** int main int i,j,r; char c; char imp; int ret; while 1 if ret = scanf"d c d",&i,&c,&j != 3 if ret == EOF exit0; printf"Erreur de syntaxe n"; exit1; imp = VRAI; switch c case '+' : r case '-' : r case '*' : r case ' ' : if  j == = i + j; break; = i - j; break; = i * j; break; 0 * * * * les op randes * e l'op rateur e * bool en de demande d'impression du r sultat e e code de retour de scanf *

*

printf"Division par z ro n"; e imp = FAUX; else r = i j; break; case '' : r = i  j; break; default : printf"l'op rateur c est incorrect n",c; imp = FAUX; e * fin du switch * if imp printf"d n",r;

62

3.17 R cr ation e e
Pour les amateurs de palindromes, voici la contribution de Brian Westley a la comp e tition du code C le plus obscur ioccc de 1987.
char rahc = " n " , redivider = "Able was I ere I saw elbA" , * deliver,reviled = 1+1 , niam ; main   * * int tni = 0x0 , rahctup,putchar   ,LACEDx0 = 0xDECAL, rof ; for ;int tni; int tni = reviled ; deliver = redivider ; for inttni++,++reviled;reviled* *deliver;deliver++,++inttni rof = int -1- tni ;reviled--;--deliver; tni = int - 0xDECAL + LACEDx0 rof ; for reviled--,int--tni;int tni;int--tni,--deliver rahctup = putchar reviled* *deliver ; rahctup * putchar char * rahc ; * *

63

L'ex cution de ce programme imprime le palindrome :  Able was I ere I saw elbA . e

R ponse de la devinette e

Non, *i *j n'est pas un quotient, car * est un d but de commentaire. Pour obtenir e le quotient de *i par *j il faut utiliser du blanc : *i *j.

64

Chapitre 4

Relations entre tableaux et pointeurs
4.1 Conversion des tableaux
Nous avons jusqu' pr sent utilis les tableaux de mani re intuitive, en nous contentant a e e e de savoir qu'on peut d clarer un tableau par une d claration du genre : e e
int t 10 ;

et qu'on dispose d'un op rateur d'indexation not , permettant d'obtenir un l ment du e e ee tableau : l' l ment d'index i du tableau t se d signe par t i . Il est temps maintenant ee e d'exposer une caract ristique originale des r f rences a un tableau dans le langage C : elles e ee subissent une conversion automatique.

R gle : e

Tout identi cateur de type  tableau de x  apparaissant dans une expression est converti en une valeur constante dont : le type est  pointeur vers x  ; la valeur est l'adresse du premier l ment du tableau. ee Cette conversion n'a lieu que pour un identi cateur de type  tableau de x  apparaissant dans une expression. En particulier, elle n'a pas lieu lors de la d claration. e Quand on d clare int T 10 , le compilateur m morise que T est de type  tableau de e e 10 int  et r serve de la place en m moire pour 10 entiers. C'est lors de toute utilisation e e ult rieure de l'identi cateur T, que cette occurrence de T sera convertie en type int *, de e valeur adresse de T 0 .

Remarques
1. La conversion automatique d'un identi cateur ayant le type tableau emp^che de e d signer un tableau en entier, c'est pour cette raison que l'op rateur d'a ectation ne e e peut a ecter un tableau a un autre tableau :
int t1 10 ;

65

int t2 10 ; t1 = t2;

*

le compilateur rejettera cette instruction

*

Un telle a ectation ne peut se r aliser qu' l'aide d'une proc dure qui r alisera e a e e l'a ectation l ment par l ment. ee ee 2. Un identi cateur ayant le type tableau est converti en une valeur constante, on ne peut donc rien lui a ecter :
int int t = p = *p; t 10 ; p; t; * * interdit valide * *

L'existence des conversions sur les r f rences aux tableaux va avoir deux cons quences ee e importantes : la premi re concerne l'op rateur d'indexation et la seconde le passage de e e tableaux en param tre. e

4.2 L'op rateur d'indexation e
La s mantique de l'op rateur d'indexation consiste dire qu'apr s les d clarations : e e a e e
int t N ; int i; t i est quivalent *t + i. V ri ons que cela est bien conforme la faon dont nous e a e a c l'avons utilis jusqu' pr sent. Nous avons vu que t pour valeur l'adresse du premier e a e a l ment du tableau. D'apr s ce que nous savons sur l'addition entre un pointeur et un ee e entier, nous pouvons conclure que t + i est l'adresse de l' l ment de rang i du tableau. ee Si nous appliquons l'op rateur d'indirection t+i nous obtenons l' l ment de rang i e a ee du tableau, ce que nous notions jusqu' pr sent t i . a e

cons quence num ro 1 e e
L'op rateur d'indexation not est donc inutile, et n'a t o ert que pour des raisons e e ee de lisibilit des programmes, et pour ne pas rompre avec les habitudes de programmation. e

cons quence num ro 2 e e
Puisque l'op rateur d'indexation s'applique des valeurs de type pointeur, on va poue a voir l'appliquer n'importe quelle valeur de type pointeur, et pas seulement aux constantes a rep rant des tableaux. En e et, apr s les d clarations : e e e
int t 10 ; int * p;

on peut crire : e
p = &t 4 ;

et utiliser l'op rateur d'indexation sur p, p 0 tant t e e donc ^tre utilis comme un sous-tableau de t. e e 66

4

,p

1

tant t e

5

, etc. p peut

cons quence num ro 3 e e
L'op rateur d'indexation est commutatif ! En e et, t i tant quivalent a *t + i e e e et l'addition tant commutative, t i est quivalent *i + t donc a i t . Lorsqu'on e e a utilise l'op rateur d'indexation, on peut noter indi remment l' l ment de rang i d'un e e ee tableau, t i ou i t . Il est bien vident que pour des raisons de lisibilit , une telle e e notation doit ^tre prohib e, et doit ^tre consid r e comme une cons quence pathologique e e e ee e de la d nition de l'op rateur d'indexation. e e

4.3 Passage de tableau en param tre e
Du fait de la conversion d'un identi cateur de type tableau en l'adresse du premier l ment, lorsqu'un tableau est pass en param tre e ectif, c'est cette adresse qui est pass e ee e e e en param tre. Le param tre formel correspondant devra donc ^tre d clar comme tant e e e e e e de type pointeur. Voyons sur un exemple. Soit crire une proc dure imp_tab qui est charg e d'imprimer ae e e un tableau d'entiers qui lui est pass en param tre. On peut proc der de la mani re e e e e suivante :
void imp_tabint *t, int nb_elem int i; for i = 0; i nb_elem; i++ printf"d ",*t + i; * d finition de imp_tab e *

Cependant, cette m thode a un gros inconv nient. En e et, lorsqu'on lit l'en-t^te de cette e e e proc dure, c'est dire la ligne : e a
void imp_tabint *t, int nb_elem

il n'est pas possible de savoir si le programmeur a voulu passer en param tre un pointeur e vers un int c'est dire un pointeur vers un seul int, ou au contraire si il a voulu a passer un tableau, c'est dire un pointeur vers une zone de n int. De faon ce que le a c a programmeur puisse exprimer cette di rence dans l'en-t^te de la proc dure, le langage C e e e admet que l'on puisse d clarer un param tre formel de la mani re suivante : e e e
void procint t ... *  * corps de la proc dure proc e

car le langage assure que lorsqu'un param tre formel de proc dure ou de fonction est e e d clar comme tant de type tableau de x, il est consid r comme tant de type pointeur e e e ee e vers x. Si d'autre part, on se souvient que la notation *t + i est quivalente la notation e a t i , la d nition de imp_tab peut s' crire : e e

67

void imp_tabint t int i; for i = 0; i

, int nb_elem

*

d finition de imp_tab e

*

nb_elem; i++ printf"d ",t i ;

Cette faon d'exprimer les choses est beaucoup plus claire, et sera donc pr f r e. L'appel c eee se fera de la mani re suivante : e 
define NB_ELEM 10 int tab NB_ELEM ; int main imp_tabtab,NB_ELEM;

Remarque
Quand une fonction admet un param tre de type tableau, il y a deux cas possibles: e soit les di rents tableaux qui lui sont pass s en param tre e ectif ont des tailles e e e di rentes, et dans ce cas la taille doit ^tre un param tre suppl mentaire de la e e e e fonction, comme dans l'exemple pr c dent ; ee soit les di rents tableaux qui lui sont pass s en param tre e ectif ont tous la m^me e e e e taille, et dans ce cas la taille peut appara^tre dans le type du param tre e ectif :
e 
define NB_ELEM 10 void imp_tabint t NB_ELEM  ...

4.4 Modi cation des l ments d'un tableau pass en paraee e m tre e
Lorsqu'on passe un param tre e ectif une proc dure ou une fonction, on a vu que e a e l'on passait une valeur. Il est donc impossible une proc dure de modi er la valeur d'une a e variable pass e en param tre. e e En ce qui concerne les tableaux par contre, on passe la proc dure l'adresse du premier a e l ment du tableau. La proc dure pourra donc modi er si elle le d sire les l ments du ee e e ee tableau. Il semble donc que le passage de tableau en param tre se fasse par adresse et non e par valeur et qu'il s'agisse d'une exception la r gle qui a rme qu'en C, tout passage a e de param tre se fait par valeur. Mais il n'en est rien : c'est la conversion automatique des e identi cateurs de type tableau qui provoque ce ph nom ne. e e 68

Du point de vue pratique, on retiendra que l'on peut modi er les l ments d'un tableau ee pass en param tre. On peut crire par exemple : e e e
* incr_tab fait + 1 sur tous les l ments du tableau t e e void incr_tabint t , int nb_elem int i; for i = 0; i nb_elem; i++ t i ++; *

4.5 Interdiction de modi cation des l ments d'un tableau ee pass en param tre e e
Lors de la normalisation du langage C, le comit en charge du travail a pens qu'il e e tait important d'introduire dans le langage un m canisme permettant au programmeur e e d'exprimer l'id e :  cette proc dure qui admet en param tre ce tableau, ne doit pas en e e e modi er les l ments . Pour r aliser cela, un nouveau mot-cl a t introduit, le mot ee e e ee const, qui permet de d clarer des variables de la mani re suivante : e e
const int i = 10;

qui d clare une variable de nom i dont il est interdit de modi er la valeur. L'int r^t de e ee const se manifeste pour les param tres de fonction. Reprenons l'exemple de la proc dure e e imp_tab, pour exprimer le fait que cette proc dure ne doit pas modi er les l ments du e ee tableau t, on peut et il est recommand de l' crire de la faon suivante : e e c
void imp_tabconst int t int i; for i = 0; i nb_elem; i++ printf"d ",t i ; , int nb_elem * d finition de imp_tab e *

4.6 Conversion des cha^nes litt rales
e
On rappelle que les cha^nes litt rales peuvent ^tre utilis es lors de la d claration avec
e e e e initialisation d'un tableau de caract res, comme ceci : e
char message = "Bonjour !!";

ou ^tre utilis es dans une expression et ^tre pass es en param tre de fonction par exemple, e e e e e comme cela :
printf"Bonjour";

69

R gle e
Lorsque les cha^nes litt rales apparaissent dans un autre contexte qu'une d claration
e e avec initialisation de tableau de caract res, elles subissent une conversion en pointeur vers e char. Si une fonction a comme param tre formel un tableau de caract res, on pourra lui e e passer en param tre e ectif aussi bien le nom d'un tableau de caract res qu'une cha^ne e e
litt rale. Exemple : e
char mess = "Bonjour"; void f char t  ... * corps de la fonction f *

fmess; f"Hello";

* *

un appel possible de f un autre appel possible de f

* *

4.7 Retour sur printf
Nous avons vu au paragraphe 1.16 que la fonction printf admet comme premier param tre une cha^ne imprimer comportant ventuellement des s quence d' chappement : e
a e e e d, o et x pour imprimer un nombre respectivement en d cimal, octal et hexad cimal et e e c pour imprimer un caract re. Il existe aussi une s quence d' chappement pour imprimer e e e les cha^nes de caract res :s. Exemple :
e
char mess1 = "Hello"; char mess2 = "Bonjour"; char *p; if ... p = mess1; else p = mess2; printf"Message = s n",p;

4.8 Exercice
1. D clarer et initialiser deux tableaux de caract res ch1 et ch2. e e 2. Ecrire une fonction lg_chaine1 qui admette en param tre un tableau de caract res e e se terminant par un null, et qui rende le nombre de caract res du tableau null exclu. e 3. Ecrire une fonction lg_chaine2 qui impl mente le m^me interface que lg_chaine1, e e mais en donnant son param tre le type pointeur vers char. a e 4. La proc dure main imprimera le nombre d' l ments de ch1 et ch2 par un appel e ee a lg_chaine1 et lg_chaine2.

70 

include

stdio.h 

define NULL_C ' 0' char ch1 = "cette cha^ne comporte 35 caract res";
e char ch2 = "et celle ci fait 30 caract res"; e ***************************************************************************** * * * lg_chaine1 * * * * But: * * calcule la longueur d'une cha^ne de caract res
e * * * * Interface: * * ch : la cha^ne de caract res
e * * valeur rendue : la longueur de ch * * * ***************************************************************************** int lg_chaine1const char ch  int i = 0; while ch i returni; != NULL_C i++; * e quivalent a whilech i  i++; *

***************************************************************************** * * * lg_chaine2 * * * * But: * * identique celui de lg_chaine1 a * * * ***************************************************************************** int lg_chaine2const char *ch int i = 0; while *ch != NULL_C i++; ch++; returni;

***************************************************************************** * main * ***************************************************************************** int main printf"la longeur de ch1 est d n",lg_chaine1ch1; printf"la longeur de ch2 est d n",lg_chaine2ch2;

71

4.9 Tableaux multidimensionnels
En C, un tableau multidimensionnel est consid r comme tant un tableau dont les ee e l ments sont eux m^mes des tableaux. Un tableau deux dimensions se d clare donc de ee e a e la mani re suivante : e
int t 10 20 ;

4.9.1 D clarations e

Les m^mes consid rations que celles que nous avons d velopp es sur les tableaux une e e e e a dimension s'appliquent, savoir : a 1. la d claration, le compilateur allouera une zone m moire permettant de stocker de a e e mani re contigue 10 tableaux de 20 entiers, soit 200 entiers ; e 2. toute r f rence ult rieure t sera convertie en l'adresse de sa premi re ligne, avec ee e a e le type pointeur vers tableau de 20 int.

4.9.2 Acc s aux l ments e ee

L'acc s un l ment du tableau se fera de pr f rence par l'expression t e a ee ee

i

j

.

4.9.3 Passage en param tre e 
define N 10 pint t ... * N  corps de p *

Lorsqu'on d sire qu'un param tre formel soit un tableau deux dimensions, il faut le e e a d clarer comme dans l'exemple suivant : e

On peut en e et omettre la taille de la premi re dimension, mais il est n cessaire d'indiquer e e la taille de la seconde dimension, car le compilateur en a besoin pour g n rer le code ee permettant d'acc der un l ment. En e et, si T est la taille des l ments de t, l'adresse e a ee ee de t i j est : adresse de +   +   . Le compilateur besoin de conna^tre N, ce a
sera donc une constante. Par contre, la taille de la premi re dimension pourra ^tre pass e e e e en param tre, comme nous l'avons fait pour les tableaux une seule dimension. Exemple : e a
t i N j T 

define P 10 void raz_matint t int i,j; for i = 0; i n; i++ for j = 0; j P; j++ t i j = 0; P , int n

72

ne sera appliquable qu' des tableaux dont la premi re dimension une taille a e a quelconque, mais dont la seconde dimension doit imp rativement avoir P l ments. e ee
raz_mat

4.10 Initialisation
Un tableau multidimensionnel peut ^tre initialis a l'aide d'une liste de listes d'exprese e sions constantes. Exemple :
int t 4 5 = 0,1,2,3,4 , 10,11,12,13,14 , 20,21,22,23,24 , 30,31,32,33,34 , ;

Un telle initialisation doit se faire avec des expressions constantes, c'est dire d livrant a e une valeur connue la compilation. a

4.11 Exercice
1. D clarer et initialiser statiquement une matrice 5,5 d'entiers tab. e 2. Ecrire une fonction print_mat qui admette en param tre une matrice 5,5 et qui e imprime ses l ments sous forme de tableau. ee 3. La proc dure main fera un appel a print_mat pour le tableau tab. e

73 

include

stdio.h 

define N 5 int tab N N =

0,1,2,3,4 , 10,11,12,13,14 , 20,21,22,23,24 , 30,31,32,33,34 , 40,41,42,43,44 ; ***************************************************************************** * * * print_mat * * * * But: * * Imprime un tableau N sur N N est une constante * * * ***************************************************************************** print_matint t N  int i,j; for i= 0; i N; i++

for j = 0; j N; j++ printf"d ",t i j ; printf" n";

***************************************************************************** * * * main * * * ***************************************************************************** int main print_mattab;

74

4.12 Tableau de pointeurs
4.12.1 Cas g n ral ee
Pour des raisons de gain de place m moire, on est parfois amen cr er des tableaux e ea e a deux dimensions dont toutes les lignes n'ont pas la m^me taille. Ceci peut se r aliser e e a l'aide d'un tableau de pointeurs vers des tableaux de tailles di rentes, associ un autre e ea tableau qui donnera la taille de chaque ligne. On obtient alors la structure de donn es e suivante :
taille tab

3

Si nous supposons que le type des objets terminaux est int, pour traduire cette structure de donn es en langage C, les programmeurs ont l'habitude de  tricher , et de ne pas e utiliser le type tableau de pointeurs vers des tableaux de int, consid r comme tant trop ee e compliqu un tel type s' crit : int *tab NB_ELEM  . La solution habituellement retee e nue, consiste a utiliser le type tableau de pointeurs vers des int, soit int *tab NB_ELEM . Voici un exemple d'une telle d claration avec initialisation statique du tableau : e 
define NB_ELEM 3 int taille NB_ELEM = 1, 2, 3 ; int ligne1 = 10 ; int ligne2 = 20,21 ; int ligne3 = 30,31,32 ; int *tab = ligne1, ligne2, ligne3 ;
j i

Pour une r f rence a l' l ment de la ligne , on n'a que l'embarras du choix. Nous donnons ee ee ci-apr s trois m thodes di rentes d'imprimer les l ments du tableau ligne par ligne. e e e ee

Premi re m thode e e
On utilise un pointeur vers un entier que l'on fait progresser d' l ment en l ment dans ee ee une ligne :

75

int i, *p; for i = 0; i

NB_ELEM; i++ + taille i ; p++ * acc s l' l ment courant par *p e a e e

for p = tab i ; p tab i printf"d ",*p; printf" n";

*

Deuxi me m thode e e
int i, j, *p; for i = 0; i

On utilise un pointeur vers le premier l ment d'une ligne ; ce pointeur reste xe. ee
NB_ELEM; i++ taille i ; j++ * acc s l' l ment courant par p j e a e e

for p = tab i , j = 0; j printf"d ",p j ; printf" n";

*

La derni re m thode est surprenante : pour la comprendre, il su t de remarquer que e e la variable p dans la seconde solution est inutile, on peut acc der l' l ment courant par e a ee la notation tab i j .
int i, j, *p; for i = 0; i NB_ELEM; i++

Troisi me m thode e e

for j = 0; j taille i ; j++ printf"d ", tab i j ; * acc s l' l ment courant par tab i e a e e printf" n";

j

*

On remarquera que c'est la m^me notation que celle qui est utilis e quand on a un vrai e e tableau deux dimensions, c'est a dire une structure de donn es physiquement compl tea e e ment di rente. Que l'acc s deux structures de donn es di rentes puissent se r aliser e e a e e e de la m^me mani re, doit sans doute ^tre consid r comme une faiblesse du langage. e e e ee C'est pour les tableaux de caract res deux dimensions, que se manifeste le plus soue a vent l'int r^t de disposer d'un tableau de lignes de longueurs di rentes : les longueurs des ee e cha^nes sont extr^mement variables. La aussi, les habitudes sont les m^mes, les program
e e meurs utilisent le type tableau de pointeurs vers des char 1 , comme ceci :
char * t NB_ELEM ;

4.12.2 Tableaux de pointeurs vers des cha^nes

1. Alors qu'en toute rigueur il faudrait utiliser le type tableau de pointeurs vers des tableaux de char

76

On peut initialiser un tableau de ce type avec des cha^nes litt rales :
e
char * mois = "janvier", "f vrier", "mars", "avril", "mai", "juin", e "juillet", "ao^t", "septembre", "octobre", "novembre", "d cembre" ; u e

On remarquera que ceci est impossible avec tout autre type que les char : il est impossible d' crire : e
int * tab = 1 , 2,3 , 4,5,6 ;

Une boucle d'impression des valeurs du tableau mois pourra ^tre : e 
define NBMOIS 12 int i; for i = 0; i NBMOIS ; i++ printf"s n",mois i ;

Les tableaux de pointeurs vers des cha^nes de caract res sont une structure de donn es
e e importante, car c'est sur celle-ci que s'appuie la transmission de param tres lors de l'ex e e cution d'un programme. Lorsqu'un utilisateur lance l'ex cution du programme prog avec e les param tres param1, param2, ... paramn, l'interpr teur de commandes collecte tous ces e e mots sous forme de cha^nes de caract res, cr e un tableau de pointeurs vers ces cha^nes,
e e
et lance la proc dure main en lui passant deux param tres : e e un entier contenant la taille du tableau ; le tableau de pointeurs vers les cha^nes.
Pour que le programme puisse exploiter les param tres pass s par l'utilisateur, la fonce e tion main doit ^tre d clar e de la mani re suivante : e e e e
int mainint argc, char *argv ... 

4.12.3 Param tres d'un programme e

Les noms argc pour argument count, ainsi que argv pour argument values, sont des noms traditionnels, mais peuvent ^tre remplac s par n'importe quels autres noms ; seuls e e les types doivent ^tre respect s. e e Comme exemple d'utilisation des param tres, nous donnons le source d'un programme e qui imprime son nom et ses param tres : e
int mainint argc, char *argv int i; printf"Nom du programme : s n", argv 0 ; for i = 1; i argc; i++ printf"Param tre d : s n",i,argv i ; e 

77

4.13 Tableau et pointeur, c'est la m^me chose? e
Il y a un moment dans l' tude du langage C, o on a l'impression que les tableaux e u et les pointeurs sont plus ou moins interchangeables, en un mot que c'est pratiquement la m^me chose. il faut donc ^tre tr s clair : un tableau et un pointeur ce n'est pas la e e e m^me chose. Quand on d clare, ailleurs qu'en param tre formel de fonction, int t 10 ; e e e on d clare un tableau, et le compilateur r serve une zone de 10 entiers cons cutifs. Quand e e e on d clare int *p, il s'agit toujours d'un pointeur, et le compilateur r serve simplement e e un l ment de m moire pouvant contenir un pointeur. ee e Les caract ristiques du langage C qui cr ent la confusion dans l'esprit des utilisateurs, e e sont les trois r gles suivantes : e 1. tout identi cateur de type tableau de x apparaissant dans une expression est converti en une valeur constante de type pointeur vers x, et ayant comme valeur l'adresse du premier l ment du tableau ; ee 2. un param tre formel de fonction, de type tableau de x est consid r comme tant e ee e de type pointeur vers x ; 3. la s mantique de l'op rateur d'indexation est la suivante : T i est quivalent e e e a *T + i.

4.13.1 Commentaires

Bien noter les points suivants : Le point important a comprendre dans la r gle 2 est que tableau de x est la m^me e e chose que pointeur vers x uniquement dans le cas de param tre formel de e fonction. Donc void fonc int t  ... est quivalent e a void fonc int * t ... . Les types des objets d clar s de type tableau ou de e e type pointeur sont di rents dans tous les autres contextes, que ce soit d claration e e de variables globales ou locales a une fonction. Di rence entre r gle 1 et r gle 2 : une d claration int t 10 qui n'est pas un e e e e param tre formel, d clare un tableau de 10 entiers. Ce sont les utilisations ult rieures e e e de t qui subissent une conversion en type pointeur vers entier. Par contre, la a d claration d'un param tre formel int t , c'est la d claration elle-m^me qui est e e e e transform e en int *t. e

4.13.2 Cas particulier des cha^nes litt rales
e
char t

Les cha^nes litt rales viennent ajouter la confusion, car on peut d clarer
e a e = "Hello"; et char *p = "Hello";. Dans le premier cas, le compilateur alloue un tableau de 6 caract res qu'il initialise avec les caract res H, e, l, l, o et 0. Toute e e occurrence de t dans une expression sera convertie en type pointeur vers char. Dans le second cas, le compilateur alloue un tableau de 6 caract res qu'il initialise de la m^me e e mani re que dans le premier cas, mais de surcro^t, il alloue une variable de type pointeur e
vers char qu'il initialise avec l'adresse du premier caract re de la cha^ne. e

78

char t

= "Hello";

t:

H

e

l

l

o

\0

char *p = "Hello";

p:

H

e

l

l

o

\0

Ceci est un cas particulier des tableaux de caract res qui ne se reproduit pas avec les e autres types. On peut d clarer un tableau d'entiers par int t = 1, 2, 3, 4, 5 ;, e mais on ne peut pas d clarer un pointeur vers un tableau d'entiers par : e int *p = 1, 2, 3, 4, 5 ;.

4.14 R cr ation e e
En illustration sur les bizarreries des tableaux dans le langage C, voici la contribution de David Korn le cr ateur du korn shell la comp tition du code C le plus obscur e a e ioccc de 1987 :
main printf&unix " 021six 012 0" ,unix "have" +"fun"-0x60;

Non, ce programme n'imprime pas have fun with unix ou quelque chose de ce genre ! Le lecteur est invit essayer d' lucider ce programme oui, il imprime quelque chose, mais ea e quoi? la solution est donn e la page suivante. e a

79

Voici les cl s de la compr hension : e e 1. Tout compilateur C poss de un certain nombre de constantes pr d nies d pendant e ee e de l'architecture de la machine sur laquelle il s'ex cute. En particulier, tout compie lateur pour machine unix pr d nit la constante unix avec comme valeur 1. Donc ee le programme est quivalent : e a
main printf&1 " 021six 012 0" ,1 "have" +"fun"-0x60;

2. Si on se souvient qu'on a vu en 4.2 que pour un tableau t, t i est quivalent e a i t , on voit que 1 " 021six 012 0" est quivalent " 021six 012 0" 1 et e a 1 "have" "have" 1 . Donc &1 " 021six 012 0" est l'adresse du caract re a e  dans la cha^ne " 021six 012 0" et "have" 1 est le caract re 'a'. On peut donc
e r crire le programme : ee
main printf"six 012 0", 'a' + "fun" -0x60;

3. La n d'une cha^ne est signal e par un caract re null  0 et le compilateur en met
e e un a la n de chaque cha^ne litt rale. Celui qui est ici est donc inutile. D'autre part,
e il existe une notation plus parlante pour le caract re de code 012 c'est dire new e a line, il s'agit de la notation n. Le programme peut donc se r crire : ee
main printf"six n", 'a' + "fun" -0x60; -0x60

4. Le caract re 'a' a pour code ascii 0x61, donc 'a' e le programme :
main printf"six n","fun" + 1;

est gal 1. R crivons e a ee

5.

"fun" + 1

donc :

est l'adresse du caract re u dans la cha^ne "fun", le programme devient e

printf"six n","un";

main

il imprime donc unix.

80

Chapitre 5

Les entr es-sorties e
A ce moment-ci de l' tude du langage, le lecteur prouve sans doute le besoin de e e disposer de moyens d'entr es-sorties plus puissants que les quelques possibilit s de printf e e et scanf que nous avons pr sent es. Nous allons donc consacrer un chapitre entier cette e e a question, en pr sentant les primitives les plus utiles de la biblioth que standard. Toutes e e les primitives ne sont pas pr sent es, mais celles qui le sont, sont pr sent es de mani re e e e e e exhaustive et conforme la norme ansi. a

5.1 Pointeur invalide
Quand on programme des listes cha^n es, on a besoin de disposer d'une valeur de
e pointeur invalide pour indiquer la n de la liste. Dans le chier d'include stddef.h se trouve la d nition d'une telle valeur qui porte le nom de NULL. Un certain nombre de e fonctions de la biblioth que standard qui doivent rendre un pointeur, utilisent la valeur e NULL comme indicateur d'erreur.

5.2 Ouverture et fermeture de chiers
5.2.1 Ouverture d'un chier : fopen
Lorsqu'on d sire acc der a un chier, il est n cessaire avant tout acc s d'ouvrir le chier e e e e a l'aide de la fonction fopen.

Utilisation
fopen nom-de-

chier

,

mode

S mantique des param tres e e
nom-de- chier est de type pointeur vers char. La cha^ne point e est le nom du chier
e auquel on veut acc der. e

81

mode est de type pointeur vers char. La cha^ne point e indique le mode d'ouverture,
e elle peut ^tre l'une des cha^ne suivantes : e
"r" ouverture d'un chier texte en lecture. "w" ouverture d'un chier texte en criture. e "a" ouverture d'un chier texte en criture a la n. e "rb" ouverture d'un chier binaire en lecture. "wb" ouverture d'un chier binaire en criture. e "ab" ouverture d'un chier binaire en criture la n. e a "r+" ouverture d'un chier texte en lecture criture. e "w+" ouverture d'un chier texte en lecture criture. e "a+" ouverture d'un chier texte en lecture criture la n. e a "r+b" ou "rb+ ouverture d'un chier binaire en lecture criture. e "w+b" ou "wb+ ouverture d'un chier binaire en lecture criture. e "a+b" ou "ab+ ouverture d'un chier binaire en lecture criture la n. e a

Remarque

La fonction fopen a t normalis e en ayant pr sent l'esprit ee e e a que certains syst mes font la distinction entre chiers binaires et e chiers textes. Cette distinction n'a pas cours dans le syst me e unix.

Valeur rendue

La fonction fopen retourne une valeur de type pointeur vers FILE, o FILE est un type u pr d ni dans le chier stdio.h. ee Si l'ouverture a r ussi, la valeur retourn e permet de rep rer le chier, et devra ^tre e e e e pass e en param tre a toutes les proc dures d'entr es-sorties sur le chier. e e e e Si l'ouverture s'est av r e impossible, fopen rend la valeur NULL. ee

Conditions particuli res et cas d'erreur e
Si le mode contient la lettre r, le chier doit exister, sinon c'est une erreur. Si le mode contient la lettre w, le chier peut, ou peut ne pas, exister. Si le chier n'existe pas, il est cr ; si le chier existe d j , son ancien contenu est perdu. ee ea Si le mode contient la lettre a, le chier peut, ou peut ne pas, exister. Si le chier n'existe pas, il est cr ; si le chier existe d j , son ancien contenu est conserv . ee ea e Si un chier est ouvert en mode  criture la n , toutes les critures se font e a e a l'endroit qui est la n du chier au moment de l'ex cution de l'ordre d' criture. Cela e e signi e que si plusieurs processus partagent le m^me FILE *, r sultat de l'ouverture e e d'un chier en criture la n, leurs critures ne s' craseront pas mutuellement. e a e e D'autre part, si un processus ouvre un chier en criture a la n, fait un fseek pour e se positionner a un endroit du chier, puis fait une criture, celle-ci aura lieu a la n e du chier pas n cessairement l'endroit du fseek. e a 82

Les voies de communication standard
Quand un programme est lanc par le syst me, celui-ci ouvre trois chiers correse e pondant aux trois voies de communication standard : standard input, standard output et standard error. Il y a trois constantes pr d nies dans stdio.h de type pointeur vers ee FILE qui rep rent ces trois chiers. Elles ont pour nom respectivement stdin, stdout et e stderr.

Utilisation typique de fopen 
include stdio.h FILE *fp; if fp = fopen"donnees","r" == NULL fprintfstderr,"Impossible d'ouvrir le fichier donn es en lecture n"; e exit1;

5.2.2 fermeture d'un chier : fclose
Quand on a termin les E S sur un chier, il faut en informer le syst me a l'aide de la e e fonction fclose.

Utilisation
fclose 

ot-de-donn es e

S mantique des param tres e e
ot-de-donn es est de type pointeur vers FILE. Il pointe vers le chier a fermer. e

Valeur rendue
La fonction fclose rend la valeur z ro si le chier a t ferm , et rend EOF si il y a eu e ee e une erreur.

Utilisation typique 
include FILE *f; stdio.h

fclosef;

83

5.3 Lecture et criture par caract re sur chier e e
5.3.1 lecture par caract re : fgetc e
Utilisation
fgetc 

ot-de-donn es e

S mantique des param tres e e
ot-de-donn es est de type pointeur vers FILE. Il pointe vers le chier a partir duquel e se fait la lecture.

Description
La fonction fgetc lit un caract re du chier ot-de-donn es. e e

Valeur rendue
Si la lecture se fait sans erreur et sans rencontre de la n de chier, fgetc rend le caract re lu. Si il y a erreur d'entr e-sortie, ou rencontre de n de chier, fgetc rend la e e valeur EOF. Pour cette raison, le type de la valeur rendue est int et non pas char.

Utilisation typique 
include stdio.h int c; FILE *fi; while c = fgetcfi != EOF ... * utilisation de c *

5.3.2 lecture par caract re : getc e
Il existe une fonction getc qui est rigoureusement identique fgetc m^me interface, a e m^me s mantique, sauf que getc est impl ment comme une macro et non comme une e e e e vraie fonction C. La di rence est que getc peut valuer plusieurs fois son param tre e e e ot-de-donn es, ce qui lui interdit d'^tre une expression contenant des e ets de bord. e e Exemple :
int i; FILE * TAB_FILE 10 ; c = getcTAB_FILE i++ ; * Arrgh..., effet de bord ! *

84

5.3.3 lecture par caract re : getchar e
Utilisation
getchar  

Description
La fonction getchar est rigoureusement quivalente getcstdin. C'est galement e a e une macro, mais comme elle n'admet pas de param tre, elle n'a pas le petit inconv nient e e de getc.

5.3.4 criture par caract re : fputc e e
Utilisation
fputc carac ,

ot-de-donn es e

S mantique des param tres e e
carac est de type int, c'est le caract re crire. e ae ot-de-donn es est de type pointeur vers FILE. Il pointe vers le chier sur lequel se e fait l' criture. e

Description
La fonction fputc crit le caract re carac dans le chier ot-de-donn es. e e e

Valeur rendue
La fonction fputc rend le caract re crit si l' criture s'est faite sans erreur, ou EOF en e e e cas d'erreur.

Utilisation typique 
include stdio.h int c; FILE *fi,*fo; * * fi : r sultat de fopen de fichier en lecture e fo : r sultat de fopen de fichier en criture e e * *

while c = fgetcfi != EOF fputcc,fo;

85

5.3.5 criture par caract re : putc e e

Il existe une fonction putc qui est rigoureusement identique fputc m^me interface, a e m^me s mantique, sauf que putc est impl ment comme une macro et non comme une e e e e vraie fonction C. La m^me remarque que celle faite au sujet de getc s'applique donc e a putc.

5.3.6 criture par caract re : putchar e e
Utilisation
putchar carac

Description
Un appel putcharc est rigoureusement identique fputcc,stdout. a

5.4 Lecture et criture par lignes sur chier e
5.4.1 lecture par ligne : fgets
Utilisation
fgets cha^ne ,

taille

,

ot-de-donn es e

S mantique des param tres e e
cha^ne est de type pointeur vers char et doit pointer vers un tableau de caract res.
e taille est la taille en octets du tableau de caract res point par cha^ne. e e
ot-de-donn es est de type pointeur vers FILE. Il pointe vers le chier a partir duquel e se fait la lecture.

Valeur rendue
La fonction fgets rend le pointeur cha^ne cas de lecture sans erreur, ou NULL dans le
cas de n de chier ou d'erreur.

Attention
Sur n de chier ou erreur, Grrr ...
fgets

rend

NULL

et non pas

EOF.

Description
La fonction fgets lit les caract res du chier et les range dans le tableau point par e e cha^ne jusqu' rencontre d'un line-feed qui est mis dans le tableau, ou rencontre de n de
a chier, ou jusqu' ce qu'il ne reste plus qu'un seul caract re libre dans le tableau. fgets a e compl te alors les caract res lus par un caract re null. e e e 86

Utilisation typique 
include stdio.h define LONG ... char ligne LONG ; FILE *fi; while fgetsligne,LONG,fi != NULL ... * utilisation de ligne * * stop sur fin de fichier ou erreur *

5.4.2 lecture par ligne : gets
Utilisation
gets cha^ne

S mantique des param tres e e
cha^ne est de type pointeur vers char et doit pointer vers un tableau de caract res.
e

Valeur rendue
gets rend NULL dans le

un pointeur vers le tableau de caract res en cas de lecture sans erreur, ou e cas de n de chier ou d'erreur.

Description
La fonction gets est un fgets sur stdin avec la di rence que le line feed n'est pas e mis dans cha^ne. Malheureusement, l'interface de gets est une catastrophe : il n'a pas le
param tre taille qui donne la taille du tableau point par cha^ne. Ceci interdit donc gets e e
a toute v ri cation pour ne pas d border du tableau. e e

Pour cette raison l'usage de gets est tr s fortement d conseill 1 e e e

5.4.3 criture par cha^ne : fputs e

Utilisation
fputs cha^ne ,

ot-de-donn es e

S mantique des param tres e e
cha^ne est de type pointeur vers char. Pointe vers un tableau de caract res contenant
e une cha^ne se terminant par un null.

1. L'attaque d'Internet connue sous le nom de  the Internet worm  a pro t de la pr sence dans le e e syst me d'un d mon qui utilisait gets. e e

87

ot-de-donn es est de type pointeur vers FILE. Il pointe vers le chier sur lequel se e fait l' criture. e

Valeur rendue
EOF

La fonction fputs rend une valeur non n gative si l' criture se passe sans erreur, et e e en cas d'erreur.

Description
sur le chier le contenu du tableau dont la n est indiqu e par un caract re e e null. Le tableau de caract res peut contenir ou non un line-feed. fputs peut donc servir e indi remment a crire une ligne ou une cha^ne quelconque. e e

fputs crit e

Utilisation typique 
include stdio.h define LONG ... char ligne LONG ; FILE *fo; fputsligne,fo;

5.4.4 criture par cha^ne : puts e

Utilisation
puts cha^ne

S mantique des param tres e e
cha^ne est de type pointeur vers char. Pointe vers un tableau de caract res contenant
e une cha^ne se terminant par un null.

Valeur rendue
EOF

La fonction fputs rend une valeur non n gative si l' criture se passe sans erreur, et e e en cas d'erreur.

Description
La fonction puts est un fputs sur stdout. Elle n'est pas entach du m^me vice r de e e hibitoire que gets, on peut donc l'utiliser. 88

5.5 E S formatt es sur chiers e
5.5.1 Ecriture formatt e : fprintf e
Utilisation
La fonction fprintf admet un nombre variable de param tres. Son utilisation est la e suivante : fprintf  ot-de-donn es , format , param 1 , param 2 , ... , param n  e

S mantique des param tres e e
ot-de-donn es est de type pointeur vers FILE. Il pointe vers le chier sur lequel se e fait l' criture. e format est une cha^ne de caract res qui sp ci e ce qui doit ^tre crit.
e e e e param i est une expression d livrant une valeur crire. e ae

Valeur rendue
La fonction fprintf retourne le nombre de caract res crits, ou une valeur n gative si e e e il y a eu une erreur d'entr e-sortie. e

Pr sentation e
La cha^ne format contient des caract res ordinaires c'est a dire di rents du caract re
e e e  qui doivent ^tre copi s tels quels, et des s quences d' chappement introduites par le e e e e caract re , d crivant la mani re dont doivent ^tre crits les param tres param 1 , param 2 , e e e e e e ... param n . Si il y a moins de param i que n'en r clame le format, le comportement n'est pas d ni. e e Si il y a davantage de param i que n'en n cessite le format, les param i en exc s sont valu s, e e e e mais leur valeur est ignor e. e

Les s quences d' chappement e e
Une s quence d' chappement se compose des l ments suivants : e e ee 1 Un certain nombre  ventuellement z ro d'indicateurs pouvant ^tre les caract res e e e e suivants :
+

blanc

param i sera cadr gauche dans son champ d'impression. ea si param i est un nombre sign , il sera imprim pr c d du signe + ou e e eee -. si param i est un nombre sign et si son premier caract re n'est pas e e un signe, on imprimera un blanc devant param i . Si on a la fois a l'indicateur + et l'indicateur blanc, ce dernier sera ignor . e

89 

cet indicateur demande l'impression de param i sous une forme non standard. Pour le format o, cet indicateur force la pr cision ^tre e ae augment e de mani re a ce que param i soit imprim en commenant e e e c par un z ro. Pour les formats x et X, cet indicateur a pour but de e faire pr c der param i respectivement de 0x ou 0X, sauf si param i est ee nul. Pour les formats e, E, f, g et G, cet indicateur force param i a ^tre imprim avec un point d cimal, m^me si il n'y a aucun chi re e e e e apr s. Pour les formats g et G, cet indicateur emp^che les z ros de la e e e n d'^tre enlev s. Pour les autres formats, le comportement n'est pas e e d ni. e pour les formats d, i, o, u, x, X, e, E, f, g, et G cet indicateur a pour e et de compl ter l' criture de param i avec des 0 en t^te, de mani re e e e e a ce qu'il remplisse tout son champ d'impression. Si il y a la fois les a deux indicateurs 0 et -, l'indicateur 0 sera ignor . Pour les formats e d, i, o, u, x et X, si il y a une indication de pr cision, l'indicateur 0 e est ignor . Pour les autres formats, le comportement n'est pas d ni. e e

0

2

Un nombre entier d cimal optionnel indiquant la taille minimum du champ e d'impression, exprim e en caract res. Si param i s' crit sur un nombre de carace e e t res inf rieur cette taille, param i est compl t droite ou gauche selon que e e a eea a l'on aura utilis ou pas l'indicateur -, avec des blancs ou des 0, comme il a t e ee expliqu plus haut. e Une indication optionnelle de pr cision, qui donne : e

3

le nombre minimum de chi res pour les formats d, i, o, u, x et X. le nombre de chi res apr s le point d cimal pour les formats e, E et f. e e le nombre maximum de chi res signi catifs pour les formats g et G le nombre maximum de caract res pour le format s. e

Cette indication de pr cision prend la forme d'un point . suivi d'un nombre e d cimal optionnel. Si ce nombre est omis, la pr cision est prise gale 0. e e e a 90

Remarque
Le nombre entier d cimal indiquant la taille maximum du e champ d'impression et ou le nombre entier d cimal indiquant e la pr cision, peuvent ^tre remplac es par le caract re *. Si le e e e e caract re * a t utilis une seule fois dans le format, la valeur e ee e correspondante taille du champ ou pr cision sera prise gale e e a param i,1 . Si le caract re * a t utilis deux fois, la taille du e ee e champ d'impression sera gale param i,2 , et la pr cision sera e a e gale a parami,1 . Si la taille maximum du champ d'impression e a une valeur n gative, cela a la s mantique de l'indicateur e e suivi de la valeur positive de la taille du champ d'impression. Si la pr cision est n gative, cela a la s mantique d'une pr cision e e e e absente. 4 un caract re optionnel, qui peut ^tre : e e
h h l l L

s'appliquant aux formats d, i, o, u, x ou X : param i sera interpr t ee comme un short int ou unsigned short int. s'appliquant au format n : param i sera interpr t comme un pointeur ee vers un short int. 2 . s'appliquant aux formats d, i, o, u, x ou X : param sera interpr t ee i comme un long int ou un unsigned long int. 3 s'appliquant au format n : param sera interpr t comme un poinee i teur vers un long int. s'appliquant aux formats e, E, f, g ou G : param i sera interpr t ee comme un long double.

5

Si un h, l ou L s'applique un autre format que ceux indiqu s a e ci-dessus, le comportement est ind termin . e e un caract re qui peut prendre les valeurs suivantes : e
d, i u o x, X

param i sera interpr t comme un int, et crit sous forme d cimale ee e e sign e. e param i sera interpr t comme un unsigned int, et crit sous forme ee e d cimale non sign e. e e param i sera interpr t comme un int, et crit sous forme octale non ee e sign e. e param i sera interpr t comme un int, et crit sous forme hexad ciee e e male non sign e. La notation hexad cimale utilisera les lettres abcdef e e dans le cas du format x, et les lettres ABCDEF dans le cas du format X.

2. la lettre elle, pas le chi re un 3. m^me remarque e

91

Dans les cas qui pr c dent, la pr cision indique le nombre minimum de chi res ee e avec lesquels crire param i . Si param i s' crit avec moins de chi res, il sera come e pl t avec des z ros. La pr cision par d faut est 1. Une valeur nulle demand e ee e e e e avec une pr cision nulle, ne sera pas imprim e. e e
c s

p n

e,E

f

g,G 

param i sera interpr t comme un unsigned char. ee param i sera interpr t comme l'adresse d'un tableau de caract res ee e termin ou non par un null. Les caract res du tableau seront ime e prim s jusqu'au premier des deux v nements possibles: e ee impression de pr cision caract res de param i . e e rencontre de null dans param i . Dans le cas o param i n'est pas termin par un null, le format d'imu e pression doit comporter une indication de pr cision. e param i sera interpr t comme un pointeur vers void. Le pointeur ee sera imprim sous une forme d pendante de l'impl mentation. e e e param i sera interpr t comme un pointeur vers un int auquel sera ee a ect le nombre de caract res crits jusqu'alors par cette invocation e e e de fprintf. param i sera interpr t comme un double et crit sous la forme : ee e -option pe . pf e signe exposant dans laquelle pe et pf sont respectivement partie enti re et partie frace tionnaire de la mantisse. La partie enti re est exprim e avec un seul e e chi re, la partie fractionnaire est exprim e avec un nombre de chi res e gal la pr cision. La pr cision est prise gale 6 par d faut. Si la e a e e e a e pr cision est 0, le point d cimal n'appara^t pas. L'exposant contient e e
toujours au moins deux chi res. Si param i est nul, l'exposant sera nul. Dans le cas du format E, la lettre E est imprim e a la place de e. e param i sera interpr t comme un double et crit sous la forme : ee e -option pe . pf dans laquelle pe et pf sont respectivement partie enti re et partie e fractionnaire de la mantisse. La partie fractionnaire est exprim e avec e un nombre de chi res gal la pr cision. La pr cision est prise gale e a e e e a 6 par d faut. Si la pr cision est 0, le point d cimal n'appara^t pas. e e e
param i sera interpr t comme un double et crit sous le format f, ou ee e le format e, selon sa valeur. Si param i a un exposant inf rieur -4 e a ou plus grand ou gal a la pr cision, il sera imprim sous le format e, e e e sinon il sera imprim sous le format f. D' ventuels z ros la n de e e e a la partie fractionnaire sont enlev s. Le point d cimal n'appara^t que e e
si il est suivi d'au moins un chi re. Dans ce qui pr c de, l'utilisation ee du format G implique l'utilisation du format E la place du format a e. Un caract re  est crit. e e

5.5.2 Ecriture formatt e : printf e

Nous avons d j vu printf, mais nous allons la d nir ici formellement. ea e 92

Utilisation
La fonction printf admet un nombre variable de param tres. Son utilisation est la e suivante : printf  format , param 1 , param 2 , ... , param n 

Description

Un appel printffmt,

... est rigoureusement identique a fprintfstdout,fmt,....

5.5.3 Ecriture formatt e dans une cha^ne : sprintf e

Utilisation
La fonction sprintf admet un nombre variable de param tres. Son utilisation est la e suivante : sprintf  cha^ne , format , param 1 , param 2 , ... , param n 

Description

La fonction sprintf r alise le m^me traitement que la fonction fprintf, avec la dife e f rence que les caract res mis par sprintf ne sont pas crits dans un chier, mais dans e e e e le tableau de caract res cha^ne. Un null est crit dans cha^ne en n de traitement. e
e

93

5.5.4 Exemples d'utilisation des formats
source C printf"|d| n",1234; printf"|d| n",-1234; printf"|+d| n",1234; printf"|+d| n",-1234; printf"| d| n",1234; printf"| d| n",-1234; printf"|x| n",0x56ab; printf"|X| n",0x56ab; printf"|x| n",0x56ab; printf"|X| n",0x56ab; printf"|o| n",1234; printf"|o| n",1234; printf"|10d| n",1234; printf"|10.6d| n",1234; printf"|.6d| n",1234; printf"|*.6d| n",10,1234; printf"|*.*d| n",10,6,1234; printf"|f| n",1.234567890123456789e5; printf"|.4f| n",1.234567890123456789e5; printf"|.20f| n",1.234567890123456789e5; printf"|20.4f| n",1.234567890123456789e5; printf"|e| n",1.234567890123456789e5; printf"|.4e| n",1.234567890123456789e5; printf"|.20e| n",1.234567890123456789e5; printf"|20.4e| n",1.234567890123456789e5; printf"|.4g| printf"|.4g| printf"|.4g| printf"|.8g| n",1.234567890123456789e-5; n",1.234567890123456789e5; n",1.234567890123456789e-3; n",1.234567890123456789e5; resultat |1234| |-1234| |+1234| |-1234| | 1234| |-1234| |56ab| |56AB| |0x56ab| |0X56AB| |2322| |02322| | 1234| | 001234| |001234| | 001234| | 001234| |123456.789012| |123456.7890| |123456.78901234567456413060| | 123456.7890| |1.234568e+05| |1.2346e+05| |1.23456789012345674564e+05| | 1.2346e+05| |1.235e-05| |1.235e+05| |0.001235| |123456.79|

5.5.5 Entr es formatt es : fscanf e e
Utilisation
La fonction fscanf admet un nombre variable de param tres. Son utilisation est la e suivante : fscanf  ot-de-donn es , format , param 1 , param 2 , ... , param n  e

S mantique des param tres e e
ot-de-donn es est de type pointeur vers FILE. Il pointe vers le chier a partir duquel e se fait la lecture.

94

format est une cha^ne de caract res qui sp ci e la forme de l'entr e admissible dans
e e e ot-de-donn es. e

les param i sont des pointeurs. Ils pointent des variables dans lesquelles fscanf d pose e les valeurs lues dans ot-de-donn es, apr s les avoir converties en binaire. e e

Valeur rendue
Si au moins un parami s'est vu a ecter une valeur, fscanf retourne le nombre de parami a ect s. Si il y a eu rencontre de n de chier ou erreur d'entr e-sortie avant toute e e a ectation un parami , fscanf retourne EOF. a

Description
fscanf lit une suite de caract res du chier d ni par ot-de-donn es en v ri ant que e e e e cette suite est conforme la description qui en est faite dans format. Cette v ri cation a e s'accompagne d'un e et de bord qui consiste a a ecter des valeurs aux variables point es e par les di rents param i . e

Quelques d nitions e ot d'entr e il s'agit de la suite de caract res lus du chier d ni par ot-de-donn es. e e e e caract res blancs il s'agit des six caract res suivants : espace, tab, line feed, new line, e e
vertical tab et form feed. 
d

mod le un mod le est la description d'un ensemble de cha^nes de caract res. Exemple : e e
e
est le mod le des cha^nes form es de chi res d cimaux, ventuellement sign es. e
e e e e
123

conforme on dira qu'une cha^ne est conforme un mod le quand elle appartient l'en
a e a
semble des cha^nes d crites par le mod le. Exemple :
e e d. est conforme au mod le e

directive une directive peut ^tre : e
une suite de caract res blancs qui est un mod le d'un nombre quelconque de e e caract res blancs. Exemple : un espace est un mod le pour un nombre quele e conque d'espaces, ou d'un nombre quelconque d'espace et de tab m lang s, ou e e d'un nombre quelconque d'espaces, de tab et de line-feed m lang s etc. e e une suite de caract res ordinaires c'est dire qui ne sont ni des caract res e a e blancs, ni le caract re  qui est un mod le pour elle-m^me. Exemple : la cha^ne e e e
hello est un mod le de la seule cha^ne hello. e
des s quences d' chappement introduites par le caract re . Ces s quences e e e e jouent un double r^le : elle sont la fois un mod le des cha^nes acceptables dans o a e
le ot d'entr e, et elles sont galement des ordres de conversion de la cha^ne lue e e
et d'a ectation du r sultat une variable point e par le parami correspondant. e a e Exemple : la directive d est un mod le des nombres d cimaux et un ordre de e e conversion de la cha^ne lue en valeur binaire et d'a ectation l'entier point
a e par le parami correspondant. 95

Les s quences d' chappement e e
Les s quences d' chappement se composent des l ments suivants : e e ee 1 le caract re * optionnel qui indique que la directive doit ^tre consid r e comme e e ee un pur mod le : pas de conversion de la cha^ne lue, et pas d'a ectation un e
a parami . 2 un nombre optionnel qui indique la longueur maximum de la cha^ne acceptable
du ot d'entr e. e 3 un caract re optionnel, qui est un modi cateur de type, pouvant prendre l'une e des valeurs suivantes :
h h l l l L

s'appliquant aux formats d, i, n : parami pointeur vers un short int. s'appliquant aux formats o, u, x : parami pointeur vers un unsigned short int. s'appliquant aux formats d, i, n : parami pointeur vers un long int. s'appliquant aux formats o, u, x : parami pointeur vers un unsigned long int. s'appliquant aux formats e, f, g : parami pointeur vers un double. s'appliquant aux formats e, f, g : parami pointeur vers un long double.

sera interpr t comme un ee sera interpr t comme un ee sera interpr t comme un ee sera interpr t comme un ee sera interpr t comme un ee sera interpr t comme un ee

4

un caract re de conversion qui peut prendre l'une des valeurs suivantes : e
d

i

o

u

mod le pour un nombre d cimal ventuellement pr c d d'un signe. e e e eee Le parami correspondant est interpr t comme un pointeur vers un ee int, sauf si la directive contient un modi cateur de type. mod le pour un nombre ventuellement pr c d d'un signe, et ayant e e eee l'une des trois formes suivantes : un nombre d cimal. e un nombre d butant par 0 qui sera pris comme nombre octal. e un nombre d butant par 0x ou 0X, qui sera pris comme nombre e hexad cimal. e Le parami correspondant est interpr t comme un pointeur vers un ee int, sauf si la directive contient un modi cateur de type. mod le pour un nombre octal ventuellement pr c d d'un signe. e e eee Le parami correspondant est interpr t comme un pointeur vers un ee unsigned int, sauf si la directive contient un modi cateur de type. mod le pour un nombre d cimal ventuellement pr c d d'un signe. 4 e e e eee Le parami correspondant est interpr t comme un pointeur vers un ee unsigned int, sauf si la directive contient un modi cateur de type. 96

4. Non, il n'y a pas d'erreur : bien que ce format soit pour des unsigned, dans le ot d'entr e, le nombre e peut ^tre pr c d d'un signe, et pas seulement +, d'ailleurs ! e eee

x

mod le pour un nombre hexad cimal ventuellement pr c d d'un e e e eee signe. Le parami correspondant est interpr t comme un pointeur ee vers un unsigned int, sauf si la directive contient un modi cateur de type.

Remarque
i

c

s

e,f,g

p

n

mod le pour une suite de caract res dont le nombre est donn par e e e le nombre optionnel qui indique la longueur maximum de la cha^ne
acceptable du ot d'entr e Cf plus haut. Si ce nombre optionnel ne e gure pas dans la directive, il est pris gal 1. Le parami correse a pondant est interpr t comme tant un pointeur vers un tableau de ee e caract res su samment grand pour contenir la cha^ne lue. Il n'y a e
pas de null rajout la n de la cha^ne lue dans le ot d'entr e. ea
e mod le pour une suite de caract res non blancs. Le parami correspone e dant est interpr t comme un pointeur vers un tableau de caract res ee e su samment grand pour contenir la cha^ne lue plus un null terminal.
mod le pour un ottant crit selon la syntaxe d'une constante ote e tante du langage C. Le parami correspondant est interpr t comme un ee pointeur vers un float , sauf si la directive contient un modi cateur de type. Dans la cha^ne format, ce caract re introduit une s quence particu
e e li re destin e d nir un scanset. La s quence est form e du caract re e e a e e e e , suivi d'une suite de caract res quelconques, suivi du caract re . Si e e le premier caract re apr s le crochet ouvrant n'est pas le caract re ^, e e e le scanset est l'ensemble des caract res entre crochets. Si le caract re e e apr s le crochet ouvrant est le caract re ^, le scanset est l'ensemble e e des caract res ne se trouvant pas dans la cha^ne entre crochets. Le e
scanset peut comprendre le caract re condition de le mettre en e a d but soit ... ou ^ ... selon que l'on utilise la forme sans e ou avec ^. Le scanset peut contenir ^ condition de ne pas le mettre a en t^te : ...^... . e Une directive est un mod le pour une suite de caract res appare e tenant au scanset. Le parami correspondant est interpr t comme ee un pointeur vers un tableau de caract res su samment grand pour e contenir la cha^ne lue plus un null terminal.
mod le pour un pointeur crit d'une mani re d pendant de l'impl e e e e e mentation, mais identique l'impression par printf d'un pointeur a selon le format p. Le parami correspondant est interpr t comme un ee pointeur vers un pointeur vers void. cette directive n'est pas un mod le. Elle ne sert qu' mettre une e a valeur dans l'objet point par le parami correspondant. Le parami e 97

En ce qui concerne les formats o, u, et x, le lecteur a sans doute t surpris de voir que le param correspondant est interpr t ee ee comme un pointeur vers un unsigned int alors que la cha^ne
dans le ot d'entr e qui correspond ces formats est un nombre e a ventuellement pr c d d'un signe. Il n'y a pas d'erreur, c'est e ee e bien ce que dit la norme. 

correspondant est interpr t comme un pointeur vers un int dans ee lequel fscanf crit le nombre de caract res lus jusqu' ce moment, e e a dans le ot de donn es, par cette invocation de fscanf. L'ex cution e e d'une directive n n'augmente pas le nombre des parami a ect s qui e sera retourn par fscanf Cf 5.5.5. e est un mod le pour le caract re . La directive compl te est . e e e

Algorithme de fscanf
La cha^ne format doit se composer d'un ensemble de directives. Il doit y avoir autant de
parami que de directives demandant l'a ectation d'une valeur. Si il n'y a pas su samment de parami pour le format, le comportement n'est pas d ni. Si il y a davantage de parami e que demand par le format, les parami en exc s sont valu s mais ils sont inutilis s. e e e e e La fonction fscanf ex cute dans l'ordre chaque directive du format. Si une directive e choue, la fonction fscanf retourne a l'appelant. e L'ex cution d'une directive form e de caract res blancs, consiste consommer dans e e e a le ot d'entr e la plus longue s quence possible de caract res blancs. M^me si cette e e e e s quence est de taille nulle, la directive a r ussi. e e L'ex cution d'une directive form e de caract res ordinaires, consiste consommer e e e a dans le ot d'entr e une s quence identique la directive. Au premier caract re e e a e di rent, la directive a chou et ce caract re reste non lu. e e e e L'ex cution d'une directive form e d'une s quence d' chappement, consiste : e e e e a 1. consommer dans le ot d'entr e la plus longue s quence possible de caract res e e e blancs. Cette s quence peut ^tre de taille nulle. Cette action ne s'applique pas e e aux formats c, n, ni . 2. consommer dans le ot d'entr e la plus longue s quence possible de caract res e e e qui soit conforme au mod le. Si cette s quence est de taille nulle, la directive a e e chou . e e 3. si la directive ne contient pas le caract re *, convertir la cha^ne lue et l'a ecter e
a l'objet point par le parami correspondant. Si cet objet n'est pas de la taille e ou du type convenable pour la recevoir, le comportement n'est pas d ni. e

Remarques sur la gestion des espaces blancs
La gestion des espaces blancs est assez p nible. Il y a deux m thodes de consommation e e des espaces blancs du ot de donn es : e 1. le format contient une directive form e de caract res blancs. Si une telle directive ne e e peut consommer aucun caract re blanc, c'est un cas d' chec de la directive. e e 2. le format contient une s quence d' chappement autre que c, n, ou  dont l'ex cution e e e commence par consommer d' ventuels caract res blancs dans le ot de donn es. Si e e e il n'y a pas de caract res blancs consommer, ce n'est pas une condition d' chec de e a e la directive. 98

Voyons quelques cons quences. e Si le ot de donn es contient 23 e

45

on pourra les lire indi remment soit : e

par le format "d d" : la premi re directive d consomme 23, la directive blanc e entre les deux d consomme les blancs entre 2 et 45, et la seconde directive d essaye de consommer des blancs, choue mais ce n'est pas une erreur, puis consomme 45. e par le format "dd" : la premi re directive d consomme 23, la seconde directive e d essaye de consommer des blancs, r ussit, puis consomme 45. e Dans les deux cas, les valeurs a ect es seront bien les m^mes : 23 et 45. e e Un tel ph nom ne ne se manifeste pas avec les s quences d' chappement dont l'ex cue e e e e tion ne commence pas par consommer les espaces blancs. Par exemple, si le ot de donn es e contient 23 jean dupond, on n'obtiendra pas le m^me r sultat selon que l'on utilise le e e format "d  abcdefghijklmnopqrstuvwxyz " ou le format "d abcdefghijklmnopqrstuvwxyz " sans blanc apr s d. Le fscanf r ussira dans e e les deux cas, mais dans le premier cas, la cha^ne a ect e au parami sera "jean dupond"
e et dans le second cas, ce sera " jean dupond".

5.5.6 Entr es formatt es : scanf e e
Nous avons d j vu scanf, nous allons la d nir ici formellement. ea e

Utilisation
La fonction scanf admet un nombre variable de param tres. Son utilisation est la e suivante : scanf  format , param 1 , param 2 , ... , param n 

Description
Un appel scanffmt,... est rigoureusement identique fscanfstdin,fmt,.... a

5.5.7 Entr es formatt es depuis une cha^ne : sscanf e e

Utilisation
La fonction sscanf admet un nombre variable de param tres. Son utilisation est la e suivante : sscanf  cha^ne , format , param 1 , param 2 , ... , param n 

Description
La fonction sscanf r alise le m^me traitement que la fonction fscanf, avec la di rence e e e que les caract res lus par sscanf ne sont pas lus depuis un chier, mais du tableau de e caract res cha^ne. La rencontre du null terminal de cha^ne pour sscanf est quivalent e

e a la rencontre de n de chier pour fscanf. 99

5.6 R cr ation e e
En illustration du printf et en guise de r cr ation, je propose un programme dont e e l'ex cution imprime le source du programme. Ce n'est pas facile du tout de cr er un tel e e programme si on exclut la version triviale consistant faire un open sur le source, le lire a et l'imprimer. Voici une solution possible que l'on trouve dans le source du compilateur gnu c :
main char*p="main char*p=csc;printfp,34,p,34,10; c";printfp,34,p,34,10;

Une indication pour le comprendre : 34 est le code ascii de " et 10 est le code ascii de newline.

5.7 Exercice 1
Soit un chier de donn es structur en une suite de lignes contenant chacune un nom e e de personne, un nom de pi ce, un nombre et un prix. Exemple : e dupond vilebrequin 10 1000 crire une proc dure main dans laquelle on d clarera les variables suivantes : e e e nom et article : tableaux de 80 caract res e nombre et prix : entiers le corps de la proc dure consistera en une boucle dont chaque it ration lira une ligne e e et l'imprimera. la lecture d'une ligne se fera par un appel a scanf a ectant les 4 champs de la ligne aux 4 variables nom, article, nombre et prix. l' criture consistera imprimer nom, article et le produit nombreprix. e a

5.8 Exercice 2
Reprendre la calculette r alis e en n de chapitre sur les pointeurs et y rajouter une e e gestion correcte des erreurs. Si l'utilisateur tape une ligne incorrecte, on d sire l' mission e e d'un message d'erreur, et une continuation de la boucle de calcul.

100 

include "stdio.h" ***************************************************************************** * * * main * * * ***************************************************************************** int main FILE * fi; char nom 80 ; char article 80 ; int nombre,prix; if fi = fopen"exer6.data","r" == NULL printf"Impossible d'ouvrir le fichier exer6.data n"; else whilefscanffi,"s s d d",nom,article,&nombre,&prix != EOF printf"s s d n",nom,article,nombre * prix; fclosefi;

101 

include enum

stdio.h

FAUX, VRAI ;

***************************************************************************** * * * main * * * ***************************************************************************** int main int i,j,r; char c; char imp; int ret; char buf_err while 1 if ret = scanf"d c d",&i,&c,&j != 3 if ret == EOF exit0; scanf" ^ n ",buf_err; * on mange la partie erron e e printf"Erreur de syntaxe : s n",buf_err; continue; imp = VRAI; switch c case '+' : r case '-' : r case '*' : r case ' ' : if  j == = i + j; break; = i - j; break; = i * j; break; 0 * les op randes * e * l'op rateur e * * bool en de demande d'impression du r sultat e e * code de retour de scanf * 80 ;

*

*

printf"Division par z ro n"; e imp = FAUX; else r = i j; break; case '' : r = i  j; break; default : printf"l'op rateur c est incorrect n",c; imp = FAUX; e * fin du switch * if imp printf"d n",r;

102

Chapitre 6

Structures, unions et num rations e e
6.1 Notion de structure
Il est habituel en programmation d'avoir besoin d'un m canisme permettant de grouper e un certain nombre de variables de types di rents au sein d'une m^me entit . On travaille e e e par exemple sur un chier de personnes et on voudrait regrouper une variable de type cha^ne de caract res pour le nom, une variable de type entier pour le num ro d'employ , etc.
e e e La r ponse ce besoin est le concept d'enregistrement : un enregistrement est un ensemble e a d' l ments de types di rents rep r s par un nom. Les l ments d'un enregistrement sont ee e ee ee appel s des champs. Le langage C poss de le concept d'enregistrement avec cependant un e e probl me de vocabulaire : e ce que tout le monde appelle le langage C l'appelle enregistrement structure champ d'un enregistrement membre d'une structure

6.2 D claration de structure e
Il y a plusieurs m thodes possibles pour d clarer des structures. e e

Premi re m thode e e
La d claration : e
struct personne char nom 20 ; char prenom 20 ; int no_employe; ;

d clare l'identi cateur personne comme tant le nom d'un type de structure compos e e e e de trois membres, dont le premier est un tableau de 20 caract res nomm nom, le second e e un tableau de 20 caract res nomm prenom, et le dernier un entier nomm no_employe. e e e Dans le jargon du langage C, l'identi cateur personne est une tiquette de structure. On e peut ensuite utiliser ce type structure pour d clarer des variables, de la mani re suivante : e e
struct personne p1,p2;

103

qui d clare deux variables de type struct e

personne

de noms p1 et p2;

Deuxi me m thode e e
On peut d clarer des variables de type structure sans utiliser d' tiquette de structure, e e par exemple :
struct char nom 20 ; char prenom 20 ; int no_employe; p1,p2;

d clare deux variables de noms p1 et p2 comme tant deux structures de trois membres, e e mais elle ne donne pas de nom au type de la structure. L'inconv nient de cette m thode e e est qu'il sera par la suite impossible de d clarer une autre variable du m^me type. En e et, e e si plus loin on crit : e
struct char nom 20 ; char prenom 20 ; int no_employe; p3;

les deux structures ont beau avoir le m^me nombre de champs, avec les m^mes noms et les e e m^mes types, elles seront consid r es de types di rents. Il sera impossible en particulier e ee e d' crire p3 = p1;. e

Troisi me m thode e e
On peut combiner d claration d' tiquette de structure et d claration de variables, e e e comme ceci :
struct personne char nom 20 ; char prenom 20 ; int no_employe; p1,p2;

d clare les deux variables p1 et p2 et donne le nom personne la structure. L aussi, on e a a pourra utiliser ult rieurement le nom struct personne pour d clarer d'autres variables : e e
struct personne pers1, pers2, pers3;

qui seront du m^me type que p1 et p2. e De ces trois m thodes c'est la premi re qui est recommand e, car elle permet de bien e e e s parer la d nition du type structure de ses utilisations. e e 104

Initialisation d'une structure
struct personne p =

Une structure peut ^tre initialis e par une liste d'expressions constantes la mani re e e a e des initialisations de tableau. Exemple :
"Jean", "Dupond", 7845 ;

6.3 Op rateurs sur les structures e

6.3.1 Acc s aux membres des structures e

Pour d signer un membre d'une structure, il faut utiliser l'op rateur de s lection de e e e membre qui se note . point. Par exemple, si p1 et p2 sont deux variables de type struct personne, on d signera le membre nom de p1 par p1.nom et on d signera le membre e e no_employe de p2 par p2.no_employe. Les membres ainsi d sign s se comportent comme e e n'importe quelle variable et par exemple, pour acc der au premier caract re du nom de e e p2, on crira : p2.nom 0 . e

6.3.2 A ectation de structures
struct personne p1,p2 ... p1 = p2;

On peut a ecter une structure une variable structure de m^me type, gr^ce l'op a e a a e rateur d'a ectation :

6.3.3 Comparaison de structures

Aucune comparaison n'est possible sur les structures, m^me pas les op rateurs == et !=. e e

6.4 Tableaux de structures
Une d claration de tableau de structures se fait selon le m^me mod le que la d claration e e e e d'un tableau dont les l ments sont de type simple. Supposons que l'on ait d j d clar la ee ea e e struct personne, si on veut d clarer un tableau de 100 structures de ce type, on crira : e e
struct personne t 100 ;

Pour r f rencer le nom de la personne qui a l'index i dans t on crira : t ee e

i .nom.

6.5 Exercice
Soit un chier de donn es identiques a celui de l'exercice pr c dent. e ee Ecrire une proc dure main qui : e 1. lise le chier en m morisant son contenu dans un tableau de structures, chaque e structure permettant de m moriser le contenu d'une ligne nom, article, nombre et e prix. 2. parcoure ensuite ce tableau en imprimant le contenu de chaque structure. 105 

include

stdio.h

***************************************************************************** * main * ***************************************************************************** int main FILE * fi; struct commande char nom 80 ; char article 80 ; int nombre,prix; ; define nb_com 100 struct commande tab_com nb_com ; int i; * int ilast;

*

tableau des commandes

*

index dans tab_com * * dernier index valide dans tab_com apr s remplissage e

*

if fi = fopen"exer7.data","r" == NULL printf"Impossible d'ouvrir le fichier exer7.data n"; else * boucle de lecture des commandes * ------------------------------i = 0; whilei * *

i++;

nb_com && fscanffi,"s s d d", tab_com i .nom, tab_com i .article, &tab_com i .nombre, &tab_com i .prix != EOF * corps du while *

if i = nb_com printf"le tableau tab_com est sous-dimentionn n"; e else * impression des commandes m moris es e e * ----------------------------------ilast = i - 1; * *

for i = 0; i = ilast; i++ printf"s s d d n", tab_com i .nom, tab_com i .article, tab_com i .nombre, tab_com i .prix; fclosefi;

106

6.6 Pointeurs vers une structure
Supposons que l'on ait d ni la struct e
struct personne ... ; personne

a l'aide de la d claration : e

on d clarera une variable de type pointeur vers une telle structure de la mani re suivante : e e
struct personne *p;

on pourra alors a ecter a p des adresses de struct
struct personne ... ; int main struct personne pers; struct personne *p; p = &pers; * *

personne.

Exemple :

pers est une variable de type struct personne p est un pointeur vers une struct personne

* *

6.7 Structures dont un des membres pointe vers une structure du m^me type e
Une des utilisations fr quentes des structures, est de cr er des listes de structures e e cha^n es. Pour cela, il faut que chaque structure contienne un membre qui soit de type
e pointeur vers une structure du m^me type. Cela se fait de la faon suivante : e c
struct personne ... * les diff rents membres e struct personne *suivant; ; personne. *

le membre de nom suivant est d clar comme tant du type pointeur vers une struct e e e La derni re structure de la liste devra avoir un membre suivant dont la valeur e sera le pointeur NULL que nous avons vu en 5.1

6.8 Acc s aux l ments d'une structure point e e ee e
personne,

Supposons que nous ayons d clar p comme tant de type pointeur vers une struct e e e comment crire une r f rence un membre de la structure point e par p ? e ee a e 107

Etant donn que *p d signe la structure, on serait tent d' crire *p.nom pour r f rencer le e e e e ee membre nom. Mais il faut savoir que les op rateurs d'indirection * et de s lection ., tout e e comme les op rateurs arithm tiques, ont une priorit . Et il se trouve que l'indirection a e e e une priorit inf rieure a celle de la s lection. Ce qui fait que *p.nom sera interpr t comme e e e ee signi ant *p.nom. Cela aurait un sens si p tait une structure dont un des membres e s'appelait nom et tait un pointeur. Dans notre cas, il faut crire *p.nom pour forcer e e l'indirection a se faire avant la s lection. e Cette criture tant assez lourde, le langage C a pr vu un nouvel op rateur not - qui e e e e e r alise a la fois l'indirection et la s lection : p - nom est identique *p.nom. Exemple : e e a si p est de type pointeur vers la struct personne d nie pr c demment, pour a ecter e ee une valeur au membre no_employe de la structure point e par p, on peut crire : e e
p no_employe = 13456;

6.9 Passage de structures en param tre e
Supposons que l'on ait fait la d claration suivante : e
struct date int jour,mois,annee; ;

une fonction de comparaison de deux dates pourra s' crire : e
enum AVANT, EGAL, APRES ;

int cmp_date struct date d1, struct date d2 if d1.annee d2.annee returnAPRES; if d1.annee d2.annee returnAVANT; ... * comparaison portant sur mois et jour

*

et une utilisation de cette fonction pourra ^tre : e
struct date d1,d2; if cmp_dated1,d2 == AVANT ...

Attention
En langage C k&r, il n'est pas possible de passer en param tre une structure, mais e on peut passer un pointeur vers une structure. 108

6.10 D termination de la taille allou e un type e e a
Pour conna^tre la taille en octets de l'espace m moire n cessaire pour une variable,
e e on dispose de l'op rateur sizeof. Cet op rateur est un op rateur unaire pr x que l'on e e e e e peut employer de deux mani res di rentes : soit sizeof expression soit sizeof  nome e de-type . Exemple :
int i,taille; taille = sizeof i; taille = sizeof short int; taille = sizeof struct personne;

6.10.1 Retour sur la conversion des tableaux
L'op rande de l'op rateur sizeof est la seule exception la conversion d'un identi cae e a teur de type tableau de x en pointeur vers x. Ne pas r aliser cette conversion est en e et e n cessaire pour que l'op rateur sizeof ait l'e et attendu par le programmeur lorsqu'il e e l'applique a un tableau. Exemple :
int t 10 ; if sizeoft sizeofint != 10 printf"sizeof mal impl ment n"; e e else printf"sizeof ok n";

6.11 Allocation et lib ration d'espace pour les structures e
Nous allons voir dans ce paragraphe trois fonctions de la biblioth que standard pere mettant d'allouer et de lib rer de l'espace. e

6.11.1 Allocation d'espace : fonctions malloc et calloc
Quand on cr e une liste cha^n e, c'est parce qu'on ne sait pas la compilation combien e
e a elle comportera d' l ments l'ex cution sinon on utiliserait un tableau. Pour pouvoir ee a e cr er des listes, il est donc n cessaire de pouvoir allouer de l'espace dynamiquement. On e e dispose pour cela de deux fonctions malloc et calloc.

Allocation d'un l ment : fonction malloc ee
La fonction malloc admet un param tre qui est la taille en octets de l' l ment d sir e ee e e et elle rend un pointeur vers l'espace allou . Utilisation typique : e 
include stdlib.h struct personne *p; p = mallocsizeofstruct personne;

109

Allocation d'un tableau d' l ments : fonction calloc ee
Elle admet deux param tres : e le premier est le nombre d' l ments d sir s ; ee e e le second est la taille en octets d'un l ment. ee son but est d'allouer un espace su sant pour contenir les l ments demand s et de rendre ee e un pointeur vers cet espace. Utilisation typique : 
include stdlib.h struct personne *p; int nb_elem; ... * init de nb_elem * p = callocnb_elem,sizeofstruct personne;

On peut alors utiliser les l ments p ee

0

,p

1

, ... p

nb_elem-1

.

On lib re l'espace allou par malloc ou calloc au moyen de la proc dure free qui e e e admet un seul param tre : un pointeur pr c demment rendu par un appel malloc ou e ee a calloc. Utilisation typique : 
include stdlib.h struct personne *p; p = mallocsizeofstruct personne; ... * utilisation de la structure allou e e freep;

6.11.2 Lib ration d'espace : proc dure free e e

*

6.12 Exercice
Modi er le programme pr c dent : ee 1. en crivant une proc dure d'impression d'une struct commande pass e en parae e e m tre. e 2. en crivant une fonction de recherche de commande maximum celle pour laquelle e le produit nombre  prix est maximum. Cette fonction admettra en param tre un e pointeur vers la struct commande qui est t^te de la liste compl te, et rendra un e e pointeur vers la structure recherch e. e 3. le main sera modi de mani re faire appel a la fonction de recherche de la come e a mande maximum et imprimer cette commande. a

110 

include include

stdlib.h stdio.h * *

* les types communs a toutes les procedures * ----------------------------------------struct commande char nom 80 ; char article 80 ; int nombre,prix; struct commande *suiv; ;

***************************************************************************** * * * print_com * * * * But: * * Imprime une structure commande * * * ***************************************************************************** void print_comstruct commande com printf"s s d d n", com.nom, com.article, com.nombre, com.prix;

111

***************************************************************************** * * * max_com * * * * But: * * Recherche la commande pour laquelle le produit nombre * prix est * * le maximun * * * * Interface: * * l_com : la liste dans laquelle doit se faire la recherche * * valeur rendue : pointeur vers la structure commande recherch e e * * ou NULL si l_com est vide * * * ***************************************************************************** struct commande *max_comstruct commande * l_com struct commande *pmax; struct commande *pcour; int vmax,vcour; if l_com == NULL returnNULL; else pmax = l_com; vmax = pmax for pcour = l_com nombre * pmax prix; * * pointeur vers le max courant * pointeur vers l'element courant

*

suiv; pcour != NULL; pcour = pcour - suiv prix;

vcour = pcour - nombre * pcour if vcour vmax vmax = vcour; pmax = pcour;

returnpmax;

112

***************************************************************************** * main * ***************************************************************************** int main FILE * fi; struct commande *l_com = NULL; struct commande *prec,*cour; int val_ret;

* * *

liste des commandes pour la commande pr c dente et courante e e valeur de retour de fscanf

* * *

if fi = fopen"exer7.data","r" == NULL printf"Impossible d'ouvrir le fichier exer7.data n"; else * * do lecture du fichier avec cr ation de la liste de commandes e --------------------------------------------------------* *

cour = mallocsizeofstruct commande; val_ret = fscanffi,"s s d d", cour - nom, cour - article, &cour - nombre, &cour - prix; if val_ret == EOF freecour; ifl_com != NULL prec else if l_com == NULL l_com = cour; else prec prec = cour; suiv = cour;

suiv = NULL;

while val_ret != EOF; * parcours de la liste avec impression * * -----------------------------------* if l_com == NULL printf"La liste de commandes est vide n"; else for cour = l_com; cour != NULL; cour = cour print_com*cour; suiv

* recherche et impression de la commande maximum * ---------------------------------------------printf"La commande maximum est : n"; print_com*max_coml_com;

* *

fclosefi;

*

fermeture du fichier

*

113

6.13 Les champs de bits
6.13.1 G n ralit s ee e
Il est parfois n cessaire pour un programmeur de d crire en termes de bits la struce e ture d'une ressource mat rielle de la machine. Un exemple typique est la programmation e syst me qui n cessite de manipuler des registres particuliers de la machine. Par exemple, e e dans le manuel du mc 68030 de Motorola, le registre d' tat est ainsi d crit : e e bit 0 : carry ; bit 1 : over ow ; bit 2 : z ro ; e bit 3 : n gatif ; e bit 4 : extension ; bits 5-7 : inutilis s ; e bits 8-10 : masque des interruptions ; bit 11 : inutilis ; e bits 12-13 : niveau de privil ge ; e bits 14-15 : tat des traces. e Il existe dans le langage C un moyen de r aliser de telles descriptions, l'aide du e a concept de structure. En e et, dans une d claration de structure, il est possible de faire e suivre la d nition d'un membre par une indication du nombre de bits que doit avoir ce e membre. Dans ce cas, le langage C appelle ca un champ de bits.  Le registre d' tat du mc 68030 peut se d crire ainsi : e e
struct sr unsigned unsigned unsigned unsigned unsigned unsigned unsigned unsigned unsigned unsigned ; int int int int int int int int int int trace : 2; priv : 2; : 1; masque : 3; : 3; extend : 1; negative : 1; zero : 1; overflow : 1; carry : 1;

* *

inutilis e inutilis e

* *

On voit que le langage C accepte que l'on ne donne pas de nom aux champs de bits qui ne sont pas utilis s. e 114

6.13.2 Contraintes

1. Les seuls types accept s pour les champs de bits sont int, unsigned int et signed e int. 2. L'ordre dans lequel sont mis les champs de bits l'int rieur d'un mot d pend de a e e l'impl mentation, mais g n ralement, dans une machine little endian les premiers e ee champs d crivent les bits de poids faibles et les derniers champs les bits de poids e forts, alors que c'est g n ralement l'inverse dans une machine big endian. ee 3. Un champ de bit d clar comme tant de type int, peut en fait se comporter comme e e e un signed int ou comme un unsigned int cela d pend de l'impl mentation. Il e e est donc recommand d'une mani re g n rale de d clarer les champs de bits comme e e ee e tant de type unsigned int. e 4. Un champ de bits n'a pas d'adresse, on ne peut donc pas lui appliquer l'op rateur e adresse de &.

6.14 Les num rations e e
Nous avons vu au paragraphe 1.10.2 que l'on pouvait d clarer des constantes nomm es e e de la mani re suivante : e
enum LUNDI, MARDI, MERCREDI, JEUDI, VENDREDI, SAMEDI, DIMANCHE ;

qui d clare les identi cateurs LUNDI, MARDI, etc. comme tant des constantes enti res de e e e valeur 0, 1, etc. Ce qui n'avait pas t dit ce moment l , c'est que les num rations ee a a e e fonctionnent syntaxiquement comme les structures : apr s le mot-cl enum il peut y avoir e e un identi cateur appel tiquette d' num ration qui permettra plus loin dans le programme ee e e de d clarer des variables de type num ration. Exemple : e e e
enum jour LUNDI, MARDI, MERCREDI, JEUDI, VENDREDI, SAMEDI, DIMANCHE ; enum jour j1, j2; j1 = LUNDI; j2 = MARDI;

L'exemple ci-dessus est conforme ce qui nous semble ^tre de bonnes r gles de proa e e grammation : d clarer d'abord le type num ration en lui donnant un nom gr^ce une e e e a a tiquette d' num ration et ensuite utiliser ce nom pour d clarer des variables. Cepene e e e dant, comme pour les structures, le langage C permet de d clarer des variables dans la e d claration du type num ration, ventuellement en omettant l' tiquette d' num ration. e e e e e e e Exemples :
enum jour LUNDI, MARDI, MERCREDI, JEUDI, VENDREDI, SAMEDI, DIMANCHE jour, d1, d2;

d clare d1 et d2 comme tant des variable de type enum e e
enum FAUX, VRAI b1,b2;

d clare b1 et b2 comme tant des variables de type num ration sans nom, dont les vae e e e leurs peuvent ^tre FAUX ou VRAI. Nous avons expliqu plus haut pourquoi un tel style de e e programmation nous semblait mauvais. 115

6.15 Les unions
Il est parfois n cessaire de manipuler des variables auxquelles on d sire a ecter des e e valeurs de type di rents. Supposons que l'on d sire crire un package math matique qui e e e e manipulera des nombres qui seront impl ment s par des int, tant que la pr cision des e e e entiers de la machine sera su sante et qui passera automatiquement a une repr sentation e sous forme de ottants d s que ce ne sera plus le cas. Il sera n cessaire de disposer de e e variables pouvant prendre soit des valeurs enti res, soit des valeurs ottantes. e Ceci peut se r aliser en C, gr^ce au m canisme des unions. Une d nition d'union e a e e a la m^me syntaxe qu'une d nition de structure, le mot cl struct tant simplement e e e e remplac par le mot cl union. Exemple : e e
union nombre int i; float f;

L'identi cateur nombre est appel tiquette d'union. La di rence s mantique entre les ee e e struct et les unions est la suivante : alors que pour une variable de type structure tous les membres peuvent avoir en m^me temps une valeur, une variable de type union ne peut e avoir un instant donn qu'un seul membre ayant une valeur. En reprenant l'exemple a e pr c dent, on d clarera une variable n de type union nombre par : ee e
union nombre n;

cette variable pourra poss der soit une valeur enti re, soit une valeur ottante, mais pas e e les deux a la fois.

6.16 Acc s aux membres de l'union e
Cet acc s se fait avec le m^me op rateur s lection not . que celui qui sert a acc der e e e e e e aux membres des structures. Dans l'exemple pr c dent, si on d sire faire poss der la ee e e a variable n une valeur enti re, on crira : e e
n.i = 10;

si on d sire lui faire poss der une valeur ottante, on crira : e e e
n.f = 3.14159;

6.17 Utilisation pratique des unions
Lorsqu'il manipule des variables de type union, le programmeur n'a malheureusement aucun moyen de savoir un instant donn , quel est le membre de l'union qui poss de a e e une valeur. Pour ^tre utilisable, une union doit donc toujours ^tre associ e une variable e e e a dont le but sera d'indiquer le membre de l'union qui est valide. En pratique, une union 116

et son indicateur sont g n ralement englob s l'int rieur d'une structure. Dans l'exemple ee e a e pr c dent, on proc dera de la mani re suivante : ee e e
enum type ENTIER, FLOTTANT ; struct arith enum type typ_val; union int i; float f; u; ; * indique ce qui est dans u *

la struct arith a deux membres typ_val float. On d clarera des variables par : e
struct arith a1,a2;

de type int, et u de type union d'int et de

puis on pourra les utiliser de la mani re suivante : e
a1.typ_val = ENTIER; a1.u.i = 10; a2.typ_val = FLOTTANT; a2.u.f = 3.14159;

Si on passe en param tre une proc dure un pointeur vers une struct arith, la proc dure e a e e testera la valeur du membre typ_val pour savoir si l'union reue poss de un entier ou un c e ottant.

6.18 Une m thode pour all ger l'acc s aux membres e e e
Quand une union est dans une structure, il faut donner un nom au membre de la structure qui est de type union, ce qui pour cons quence de rendre assez lourd l'acc s a e e aux membres de l'union. Dans l'exemple pr c dent, il faut crire a1.u.f pour acc der au ee e e membre f. On peut all ger l' criture en utilisant les facilit s du pr processeur. On peut e e e e crire par exemple : e 
define I u.i define F u.f

Pour initialiser a1 avec l'entier 10, on crira alors : e
a1.typ_val = ENTIER; a1.I = 10;

117

118

Chapitre 7

Les expressions
Ce chapitre d bute par l' tude des conversions, probl me qui avait t peine e eur e e e eea e quand nous avions parl des op rateurs. Il se poursuit par la pr sentation des op rateurs e e e e non encore vus et se termine par l' tude de la s mantique des expressions. e e

7.1 Les conversions de types
Dans un programme, dans un contexte o l'on attend une valeur d'un certain type, il u faut normalement fournir une valeur de ce type. Par exemple, si la partie gauche d'une a ectation est de type ottant, la valeur fournie en partie droite doit galement ^tre de e e type ottant. Il est cependant agr able de ne pas ^tre trop strict sur cette r gle. Si le type e e e attendu et le type de la valeur fournie sont trop di rents, on attend un ottant et on e fournit une structure, il est normal que le compilateur consid re qu'il s'agit d'une erreur e du programmeur. Si par contre, le type attendu et le type de la valeur fournie sont assez  proches  , c'est une facilit agr able que le compilateur fasse lui-m^me la conversion. On   e e e peut admettre par exemple, que dans un contexte o on attend un nombre ottant, on u puisse fournir un nombre entier. Autre situation o les conversions sont utiles : les expressions. Les machines physiques u sur lesquelles s'ex cutent les programmes comportent des instructions di rentes pour r ae e e liser de l'arithm tique sur les entiers et sur les ottants. Cette situation se retrouve dans e les langages de programmation de bas niveau les assembleurs o le programmeur doit u utiliser des op rateurs di rents pour r aliser la m^me op ration au sens math matique e e e e e e du terme selon qu'elle porte sur des entiers ou des ottants. Les langages de programmation de haut niveau par contre, surchargent les symboles des op rateurs arithm tiques e e de mani re a ce que le m^me symbole puisse r aliser une op ration indi remment entre e e e e e entiers ou entre ottants : le symbole + permet de r aliser l'addition de deux entiers ou e deux ottants. Ceci est d j une facilit agr able, mais il est possible d'aller plus loin. Le ea e e langage peut autoriser le programmeur donner aux op rateurs des op randes de types a e e di rents, charge au compilateur de faire une conversion de type sur l'un ou l'autre des e op randes pour les amener a un type commun. e En n, il se peut que le langage o re au programmeur la possibilit de demander exe plicitement une conversion de type : si le langage pascal n'o re pas une telle possibilit , e le langage C par contre dispose d'un op rateur de conversion de type. e 119

7.1.1 Utilit des conversions e

7.1.2 Ce qu'il y a dans une conversion
Pour comprendre ce qui se passe dans une conversion il faut bien distinguer type, valeur et repr sentation. La repr sentation d'une valeur est la cha^ne de bits qui compose e e
cette valeur dans la m moire de la machine. La repr sentation des entiers est une suite de e e bits en notation binaire simple pour les positifs, g n ralement en compl ment 2 pour les ee e a n gatifs. La repr sentation des ottants est plus compliqu e, c'est g n ralement un triplet e e e ee de cha^nes de bits : signe, mantisse, exposant.
Une conversion a pour but de changer le type d'une valeur, sans changer cette valeur si c'est possible ; elle pourra ventuellement s'accompagner d'un changement de repr sene e tation. Exemple de conversion avec changement de repr sentation : la conversion d'entier vers e ottant ou vice versa. Exemple de conversion sans changement de repr sentation : la e conversion d'entier non sign vers entier sign ou vice versa, sur une machine o les entiers e e u sign s sont repr sent s en compl ment 2. e e e e a

7.1.3 L'ensemble des conversions possibles
matique de l'objet. Si ce n'est pas possible :

Conversions vers un type entier depuis un type entier La r gle est de pr server, si c'est possible, la valeur math e e e
si le type destination est un type sign , on consid re qu'il y a d passement de e e e capacit et la valeur du r sultat n'est pas d nie. e e e si le type destination est un type non sign , la valeur du r sultat doit ^tre e e e gale modulo n la valeur originale, o n est le nombre de bits utilis s pour e a u e repr senter les valeur du type destination. e Dans ce qui suit, on se place pr cis ment dans la cas o la machine repr sente les e e u e nombres sign s en compl ment 2 c'est le cas de pratiquement toutes les machines. e e a Une conversion d'un entier sign vers un entier non sign , ou vice versa, se fait sans e e changement de repr sentation. Une conversion d'un entier vers un entier plus court e se fait par troncature des bits les plus signi catifs. Une conversion d'un entier vers un entier plus long se fait par extension du bit de signe si le type originel est sign , e par extension de z ros si le type originel est non sign . e e

depuis un type ottant La r gle est de pr server, si c'est possible, la valeur e e math matique de l'objet, sachant qu'il peut y avoir une erreur d'arrondi. e
est consid r comme un type entier non sign de la m^me taille que les pointeurs. Il ee e e est ensuite converti dans le type destination selon les r gles de conversions d'entiers e vers entiers.

depuis un pointeur Un pointeur peut ^tre converti en un type entier. Pour cela il e

Conversions vers un type ottant
Seuls les types entiers et ottants peuvent ^tre convertis en un type ottant. L aussi, e a la r gle est de pr server la valeur si possible, sinon c'est un cas d'over ow ou d'under ow. e e 120

Conversion vers un type pointeur
Les di rentes possibilit s sont les suivantes : e e Un type pointeur vers 1 peut ^tre converti en un type pointeur vers 2 quels que e soient 1 et 2. La valeur enti re 0 peut ^tre convertie en un type pointeur vers quel que soit , e e et c'est la valeur dite de pointeur invalide. Une valeur enti re non nulle peut ^tre convertie en un type pointeur vers quel que e e soit , mais cela est explicitement non portable. Nous avons vu pr c demment au paragraphe 4.1 : ee Toute expression de type tableau de x est convertie en type pointeur vers x. Il y a une r gle similaire concernant les fonctions : e Toute expression de type fonction retournant x est convertie en type pointeur vers fonction retournant x.
T T T T T T T T

Conversion vers le type void
N'importe quelle valeur peut ^tre convertie vers le type void. Cela n'a de sens que si e la valeur r sultat n'est pas utilis e. e e

7.1.4 Les situations de conversions

Dans le langage C, les situations o se produisent les conversions sont les suivantes : u 1. une valeur d'un certain type est utilis e dans un contexte qui en demande un autre. e passage de param tre : le param tre e ectif n'a pas le type du param tre formel ; e e e a ectation : la valeur a ecter n'a pas le m^me type que la variable ; a e valeur rendue par une fonction : l'op rande de return n'a pas le type indiqu e e dans la d claration de la fonction. e 2. op rateur de conversion : le programmeur demande explicitement une conversion. e 3. un op rateur a des op randes de types di rents. e e e Dans les cas 1 et 2, type de d part et type d'arriv e de la conversion sont donn s. Dans e e e le cas 3, par contre, c'est le compilateur qui choisit le type d'arriv e de la conversion. Il le e fait selon des r gles soigneusement d nies. Il y en a deux dans le langage C qui portent e e les noms de  promotion des entiers  et  conversions arithm tiques habituelles . e

Ce que l'on appelle dans le langage C promotion des entiers est une r gle de conversion e des op randes dans les expressions. La promotion des entiers a pour but d'amener les e  petits entiers  la taille des int.   a 121

7.1.5 La promotion des entiers

Domaine d'application
La promotion des entiers est appliqu e l'op rande des op rateurs unaires +, - et ~, e a e e ainsi qu'aux deux op randes des op rateurs de d calage et . La promotion des entiers e e e est galement utilis e dans la d nition des conversions arithm tiques habituelles . e e e e

La r gle e
Une valeur de type char, un short int ou un champ de bits, ou d'une version sign e ou e non sign e des pr c dents, peut ^tre utilis e dans un contexte o un int ou un unsigned e ee e e u int est demand . Cette valeur est convertie en un int ou un unsigned int d'une mani re e e h las d pendante de l'impl mentation : e e e si un int peut repr senter toutes les valeurs du type de d part, la valeur est convertie e e en int ; sinon, elle est convertie en unsigned int.

7.1.6 Les conversions arithm tiques habituelles e
Domaine d'application
Les conversions arithm tiques habituelles sont r alis s sur les op randes de tous les e e e e op rateurs arithm tiques binaires sauf les op rateurs de d calage et ainsi que sur e e e e les second et troisi me op randes de l'op rateur ?:. e e e

La r gle e

1. Si un op rande est de type long double, l'autre op rande est converti en long e e double. 2. Sinon si un op rande est de type double, l'autre op rande est converti en double. e e 3. Sinon si un op rande est de type float, l'autre op rande est converti en float. e e 4. Sinon la promotion des entiers est r alis e sur les deux op randes. Ensuite : e e e a. Si un op rande est de type unsigned long int, l'autre op rande est converti e e en unsigned long int. b. Sinon, si un op rande est de type long int et l'autre de type unsigned int, e alors : si un long int peut repr senter toutes les valeurs d'un unsigned int, e l'op rande de type unsigned int est converti en long int. e sinon, les deux op randes sont convertis en unsigned long int. e c. Sinon, si un op rande est de type long int, l'autre op rande est converti en e e long int. d. Sinon, si un op rande est de type unsigned int, l'autre op rande est converti e e en unsigned int. e. Sinon, les deux op randes sont de m^me type, et il n'y a pas de conversion e e a r aliser. e 122

Discussion
Les points 1, 2, 3 sont faciles a comprendre : si les deux op randes sont ottants, celui e de moindre pr cision est converti dans le type de l'autre. Si un seul des op randes est de e e type ottant, l'autre est converti dans ce type. On aborde le point 4 si les deux op randes sont des vari t s d'entiers courts, normaux e ee ou longs, sign s ou non sign s. On applique alors la promotion des entiers, de mani re e e e a se d barrasser des entiers courts. A la suite de cela, il n'y plus comme types possibles que e int, unsigned int, long int et unsigned long int. Si l'on excepte les cas o les deux types sont identiques, le reste des r gles peut se u e r sumer dans le tableau suivant : e
unsigned long int long int long int unsigned int

op rande e

op rande e quelconque
unsigned int int int

unsigned long int long int unsigned long int long int unsigned int

r sultat e

D'une mani re g n rale, les conversions sont un m canisme qui fonctionne la satise ee e a faction du programmeur. Il y a cependant une situation o cela peut donner des r sultats u e surprenants : quand on r alise une comparaison entre entiers sign s et entiers non sign s. e e e Par exemple, le programme suivant :
int main unsigned int i = 0; if i -1  printf"Bizarre, bizarre ... n"; else printf "Tout semble normal n";

7.1.7 Les surprises des conversions

imprimera le message Bizarre, bizarre ..., pouvant laisser croire que pour le langage C, 0 est inf rieur ,1. e a L'explication est la suivante : l'op rateur a un op rande de type unsigned int la e e variable i, et un autre op rande de type int la constante -1. D'apr s le tableau des e e conversions donn ci-dessus, on voit que dans un tel cas, les op randes sont convertis e e en unsigned int. Le compilateur g n re donc une comparaison non sign e entre 0 et ee e 4294967295 puisque -1 = 0x = 4294967295, d'o le r sultat. u e Pour que tout rentre dans l'ordre, il su t d'utiliser l'op rateur de conversion pour e pr venir le compilateur de ce qu'on veut faire : e
int main unsigned int i = 0;

123

if int i -1  * comparaison entre deux int printf"Bizarre, bizarre ... n"; else printf "Tout semble normal n";

*

L o tout se complique c'est qu'on peut utiliser des entiers non sign s sans le savoir ! a u e Consid rons le programme suivant : e
int main if sizeofint -1 printf"Bizarre, bizarre ... n"; else printf "Tout semble normal n";

le lecteur a sans doute devin qu'il va imprimer le message Bizarre, bizarre ..., et e cependant les entiers n'ont pas une longueur n gative ! L'explication est la suivante : l'op e e rateur sizeof rend une valeur dont le type est non sign . Voici ce que dit exactement la e norme :  La valeur du r sultat de sizeof d pend de l'impl mentation, et son type un e e e e type entier non sign  est size t qui est d nit dans le chier d'include stddef.h . Dans e notre exemple, le compilateur a g n r une comparaison non sign e entre 4 sizeofint e ee e et 4 294 967 295, d'o le r sultat. u e

Recommandations
1. Ne jamais m langer des entiers sign s et non sign s dans des comparaisons : utilie e e ser l'op rateur de conversion pour amener l'op rateur de comparaison avoir des e e a op randes de m^me type. e e 2. Bien noter que l'op rateur sizeof rend une valeur de type entier non sign . e e

7.2 Les op rateurs e
Nous avons tudi les op rateurs arithm tiques usuels dans le chapitre sur les bases e e e e du langage, les op rateurs incr ment et d cr ment dans le chapitre sur les tableaux, les e e e e op rateurs d'adresse dans le chapitre sur les pointeurs et les op rateurs de s lection dans e e e le chapitre sur les structures. Le langage C comporte quelques autres op rateurs que nous allons tudier ci-apr s. e e e

7.2.1 Op rateur non bit bit e a
Syntaxe : expression : 

~

expression

S mantique : e expression est valu e et doit d livrer une valeur de type entier, l'op ration non bit e e e e a bit est r alis e sur cette valeur, et le r sultat obtenu est la valeur de l'expression ~. e e e 124

7.2.2 Op rateur et bit bit e a
Syntaxe : expression : 

expression 1

&

expression 2

S mantique : e Les deux expressions sont valu es et doivent d livrer des valeurs de type entier, le e e e et bit bit est r alis , et la valeur obtenue est la valeur de l'expression &. a e e

7.2.3 Op rateur ou bit bit e a
Syntaxe : expression : 

expression 1

|

expression 2

S mantique : e Les deux expressions sont valu es et doivent d livrer des valeurs de type entier, le e e e ou bit bit est r alis , et la valeur obtenue est la valeur de l'expression |. a e e

7.2.4 Op rateur ou exclusif bit bit e a
Syntaxe : expression : 

expression 1

^

expression 2

S mantique : e Les deux expressions sont valu es et doivent d livrer des valeurs de type entier, le e e e ou exclusif bit a bit est r alis , et la valeur obtenue est la valeur de l'expression ^. e e

7.2.5 Op rateur d calage gauche e e a
Syntaxe : expression : 

expression 1

expression 2

S mantique : e Les deux expressions sont valu es et doivent d livrer des valeurs de type entier, la e e e valeur de expression 1 est d cal e a gauche de expression2 bits en remplissant les bits e e libres avec des z ros. Le r sultat obtenu est la valeur de l'expression . e e

7.2.6 Op rateur d calage droite e e a
Syntaxe : expression : 

expression 1

expression 2

125

S mantique : e Les deux expressions sont valu es et doivent d livrer des valeurs de type entier, la e e e valeur de expression 1 est d cal e droite de expression2 bits. Si expression 1 d livre e e a e une valeur unsigned, le d calage est un d calage logique : les bits lib r s sont remplis e e ee avec des z ros. Sinon, le d calage peut ^tre logique ou arithm tique les bits lib r s e e e e ee sont remplis avec le bit de signe, cela d pend de l'impl mentation. e e

7.2.7 Op rateur conditionnel e
Syntaxe : expression : 

expression 1

?

expression 2

:

expression 3

S mantique : e expression 1 est valu e et doit d livrer une valeur de type entier. Si cette valeur est : e e e non nulle, expression 2 est valu e et le r sultat est la valeur de l'expression e e e conditionnelle. nulle, expression 3 est valu e et le r sultat est la valeur de l'expression condie e e tionnelle.

Exemples
Cet op rateur permet de remplacer une instruction if : e
max = a b ? a : b;

On peut utiliser cet op rateur en cascade, mais la lisibilit en sou re : e e
printf"i est s",i 0 ? "negatif n" : i 0 ? "positif n" : "nul n";

7.2.8 Op rateur virgule e
Syntaxe : expression : 

expression 1

,

expression 2

S mantique : e expression 1 est valu e et sa valeur ignor e. expression 2 est valu e et sa valeur est e e e e e la valeur de l'expression virgule. Etant donn que la valeur de expression 1 est ignor e, pour qu'une telle construction e e ait un sens, il faut que expression 1 fasse un e et de bord. On peut crire par exemple : e
i = j = 2 , 1;

Remarque

126

ce qui est une mani re particuli rement horrible d' crire : e e e
i = 1; j = 2;

Une utilisation agr able par contre de l'op rateur virgule est dans les expressions d'une e e boucle for. Si on d sire crire une boucle for qui utilise deux index, il est utile d' crire e e e par exemple :
for i = 1, j = 1; i ... = LIMITE; i++, j = j + 2

j = j + 2

ceci permet de rendre manifeste que i = 1 et j sont la partie it ration de la boucle. e

= 1

sont la partie initialisation et i++ et

7.2.9 Op rateurs d'a ectation compos e e e
Chacun des op rateurs + - *  e & ^ | peut s'associer l'op rateur d'a eca e tation pour former respectivement les op rateurs += -= *= = = = = &= ^= |=. e Nous donnerons la syntaxe et la s mantique de ces op rateurs dans le cas de l'op rateur e e e +=, celles des autres s'en d duit imm diatement. e e Syntaxe : expression : 

lvalue

+=

expression expression

S mantique : e lvalue = lvalue

+

7.3 Op rateur conversion e
Syntaxe : expression :  

type 

expression

S mantique : expression est valu e et convertie dans le type indiqu par type. e e e e

Note
Dans le jargon C, l'op rateur de conversion de type s'appelle un cast. Dans le vocae bulaire des langages de programmation en g n ral, une conversion de type s'appelle en ee anglais une coertion, que l'on peut traduire par contrainte ou coercition. Le mot anglais cast signi e pl^tre pour maintenir un membre bris , il donne donc bien une id e de a e e contrainte, mais c'est quand m^me un choix bizarre. e 127

Exemples d'utilisation
L'op rateur de conversion est devenu moins utile avec la normalisation du langage C. e Dans k&r C, il tait utilis essentiellement pour deux raisons : e e 1. cause de l'absence de pointeur g n rique void *. En e et, les proc dures d'allocaa ee e tion de m moire comme malloc taient d nies par : e e e
extern char * malloc;

ce qui n cessitait d'utiliser l'op rateur de conversion de type a chaque utilisation : e e
p1 = struct s1 * mallocsizeofstruct s1; p2 = struct s2 * mallocsizeofstruct s2;

2. cause de l'absence de prototype de fonction qui rendait impossible la d claration a e du type des param tres des fonctions externes. Si une proc dure p attendait un e e param tre de type float, et si on d sirait lui passer la valeur poss d e par la variable e e ee i de type int, il ne fallait pas crire pi mais pfloat i. e Il reste cependant un certain nombre de situations o l'op rateur de conversion est u e n cessaire. En voici un exemple. Il s'agit d'un programme qui a pour but de d terminer si e e l'architecture de la machine est de type little endian ou big endian. Il faut regarder l'ordre des octets dans un entier, d'o la n cessit de l'op rateur de conversion. Ce programme u e e e suppose que les int sont impl ment s sur 4 octets. e e
int i = 0x01020304; char *p; p = char * &i; * int * transform en char * e * if *p++ == 1 && *p++ == 2 && *p++ == 3 && *p++ == 4  printf"big endian n"; else p = char * &i; if *p++ == 4 && *p++ == 3 && *p++ == 2 && *p++ == 1  printf"little endian n"; else printf"architecture exotique !! n";

Ex cut sur une machine Sun processeur sparc, ce programme r pondra big endian, e e a e ex cut sur un pc processeur Intel, il r pondra little endian. e e a e 128

7.4 S mantique des expressions e
7.4.1 Op rateurs d'adressage e
Dans le langage C, les constructions suivantes : 

* . &

pour l'appel de proc dure e pour l'indexation pour l'indirection pour la s lection de champ e pour l'indirection et s lection e pour d livrer l'adresse d'un objet e

sont des op rateurs part enti re. Cela signi e que ces op rateurs, que l'on peut appeler e a e e op rateurs d'adressage, ont une priorit et sont en concurrence avec les autres op rateurs e e e pour d terminer la s mantique d'une expression. Par exemple, la s mantique de l'exprese e e sion *p++ ne peut se d terminer que si l'on conna^t les priorit s relatives des op rateurs * e
e e et ++.

7.4.2 Priorit et associativit des op rateurs e e e
Pour d terminer la s mantique d'une expression il faut non seulement conna^tre la e e
priorit des op rateurs mais galement leur associativit . En e et, seule la connaissance de e e e e l'associativit de l'op rateur == permet de savoir si a == b == c signi e a == b == c e e ou si elle signi e a == b == c.
a a

Un op rateur a une associativit droite quand : e ea op b op c signi e a op  b op c. Un op rateur a une associativit gauche quand : e ea op b op c signi e a op b op c.

Nous donnons ci-dessous le tableau exhaustif des op rateurs avec leurs priorit s et leurs e e associativit . e 129

priorit Op rateur e e 16  15 ! ~ ++ c 14 conversion 13 *i  12 + 11 10 = == != 9 8 &j 7 ^ | 6 5 && || 4 3 ?: 2 = += -= 1 ,
post x e post x e c pr x e e d pr x e e e unaire f unaire g indirection h adresse de i multiplication j et bit bit
a b

. ++ a -- b -- d - e + f

*g

&h

sizeof

=

*=

= 

=

=

=

&=

^=

|=

Associativit e G D D G G G G G G G G G G D D G

Discussion
Les choix faits pour les priorit s des op rateurs sont assez mauvais, les concepteurs du e e langage eux-m^mes en conviennent. 1 Les choix les plus irritants sont les suivants : e La pr c dence des op rateurs bits bits est plus petite que celle des op rateurs de ee e a e comparaison. Donc a&b == c ne signi e pas a&b == c, mais a & b==c. La pr c dence des op rateurs de d calage est plus petite que celle des op rateurs de ee e e e + et -. Donc a 4 + b signi e a 4 + b.

Recommandation
Il est consid r comme un bon style de programmation en C, de syst matiquement ee e parenth ser les expressions d s qu'elles comportent d'autres op rateurs que les op rateurs e e e e de l'arithm tique usuelle. e
1. The C programming langage, page 3 : C, like any other language, has its blemishes. Some of the operators have the wrong precedence;

130

7.4.3 Ordre d' valuation des op randes e e

A part quelques exceptions, l'ordre d' valuation des op randes d'un op rateur n'est pas e e e sp ci par le langage. Ceci a pour cons quence que le programmeur doit faire extr^mement e e e e attention aux e ets de bords dans les expressions. Par exemple, l'instruction :
t i = f;

o la fonction f modi e la valeur de i a un comportement ind termin : il est impossible u e e de savoir si la valeur prise pour indexer t sera celle de i avant ou apr s l'appel a f. e

7.5 R cr ation e e
Voici en illustration de l'op rateur ~, la contribution de Jack Applin a la comp tition e e du code C le plus obscur ioccc de 1986. Ce programme a la propri t extraordinaire ee d'^tre un source valide a la fois pour le shell bin sh, le langage C et fortran ! Voici le e source :
cat =13 * dev null 2 &1; echo "Hello, world!"; exit * * This program works under cc, f77, and bin sh. * * ; main write cat-~-cat *,' * ,"Hello, world!" , cat; putchar~-~-~-cat; * ,' end *

La version shell
La commande cat =13 est une commande incorrecte  cause du blanc entre cat et le a signe =, mais comme l'erreur standard est redirig e sur dev null, le message d'erreur e n'appara^t pas. Ensuite, l'echo imprime  Hello world , puis le shell fait exit. Le reste
du source lui est donc indi rent. Ensuite, les deux versions C et fortran sont m lang es e e e gr^ce a un emploi judicieux des commentaires en fortran, toute ligne commenant par * a c ou c est un commentaire.

La version fortran
Une fois d barrass des commentaires fortran, le source devient : e e
write *,'"Hello, world!"' end

ce qui imprime  Hello world . 131

La version C
Apr s nettoyage des commentaires C, le source original devient : e
cat =13 ; main write cat-~-cat ,"Hello, world!" , cat; putchar~-~-~-cat;

La d claration cat =13 ; est valide en C k&r mais obsol te en ansi C : elle est quivae e e lente int cat =13 ; Cette forme est cependant encore g n ralement accept e avec un a ee e warning par les compilateurs. La suite ne fonctionne correctement que sur une machine satisfaisant aux deux contraintes suivantes : 1. ^tre une machine unix pour disposer de l'appel noyau write ; e 2. avoir les entiers n gatifs repr sent s en compl ment 2. Dans ce cas en e et, ~-x e e e e a vaut x - 1. Donc cat-~-cat vaut 1 qui, en premier param tre de write d signe la sortie standard, et e e ~-~-~-13 vaut 10 le code de newline. Le troisi me param tre pass write doit ^tre la e e ea e longueur de la cha^ne imprimer, ici 13 qui est bien la longueur de Hello, world!. Au
a nal, ce programme imprime  Hello world .

132

Chapitre 8

Le pr processeur e
Les services rendus par le pr processeur sont : l'inclusion de chier source, le traitement e de macros et la compilation conditionnelle. L'inclusion de chier source a d j t vue dans eae e le chapitre 1.14 nous n'y reviendrons pas.

8.1 Traitement de macros
Il existe deux types de macros : les macros sans param tre et les macros avec parae m tres. e

8.1.1 Les macros sans param tres e
Les macros sans param tre ont t introduites au paragraphe 1.10.1. Rappelons que e ee lorsque le pr processeur lit une ligne du type : e 
define

nom reste-de-la-ligne

il remplace dans toute la suite du source, toute nouvelle occurrence de nom par reste-dela-ligne. Il n'y a aucune contrainte quand ce qui peut se trouver dans reste-de-la-ligne, a mais l'utilit principale des macros sans param tre est de donner un nom parlant une e e a constante. Les avantages toujours donner un nom aux constantes sont les suivants : a 1. un nom bien choisi permet d'expliciter la s mantique de la constante. Exemple : e define NB_COLONNES 100. 2. la constante chi r e se trouve un seul endroit, ce qui facilite la modi cation du e a programme quand on veut changer la valeur de la constante cas de la taille d'un tableau, par exemple. 3. on peut expliciter les relations entre constantes. Exemple : 
define NB_LIGNES 24 define NB_COLONNES 80 define TAILLE_TAB NB_LIGNES * NB_COLONNES

133

Exemple de mauvaise utilisation
Du fait de l'absence de contrainte sur reste-de-la-ligne, on peut faire des choses tr s e d raisonnables avec les macros. Un exemple c l bre est le source du shell crit par Steve e ee e Bourne pour le syst me unix. Bourne avait utilis les facilit s de macros pour programmer e e e dans un dialecte de Algol 68. Voici un extrait de ses d nitions : e 
define define define define define IF THEN ELSE ELIF FI if  else else if  ; 

define BEGIN define END define SWITCH define IN define ENDSW define FOR define WHILE define DO define OD define REP define PER undef DONE define DONE define LOOP define POOL

switch  for while  ; do while ; for;;

Et voici un exemple de code :
assignn,v NAMPTR STRING n; v;

IF n- namflg&N_RDONLY THEN failedn- namid,wtfailed; ELSE replace&n- namval,v; FI

Ce n'est ni du C ni de l'Algol, il y a un consensus dans la communaut C pour estimer e que ce genre de choses est a proscrire.

D nition de macro l'invocation du compilateur e a
Certains compilateurs permettent de d nir des macros sans param tres l'invocation e e a du compilateur. Il est alors possible d' crire un programme utilisant une macro qui n'est e nulle part d nie dans le source. La d nition se fera l'invocation du compilateur. Ceci e e a 134

est tr s pratique pour que certaines constantes critiques d'un programme aient une valeur e qui soit attribu e a l'ext rieur du programme, par une phase de con guration par exemple. e e Ci-dessous, un exemple pour le syst me unix : la compilation du chier fic.c en e d nissant la macro sans param tre de nom NB LIGNES et de valeur 24 : e e
cc -c -DNB_LIGNES=24 fic.c

8.1.2 Macros pr d nies ee
Il y a un certain nombre de macros pr d nies par le pr processeur : ee e nom
__LINE__ __FILE__ __DATE__ __TIME__ __STDC__

valeur de la macro forme syntaxique num ro de la ligne courante du programme source e entier nom du chier source en cours de compilation cha^ne
la date de la compilation cha^ne
l'heure de la compilation cha^ne
1 si le compilateur est iso, 0 sinon entier

8.1.3 Les macros avec param tres e 
define

Une macro avec param tres se d nit de la mani re suivante : e e e nom  liste-de-param tres-formels  reste-de-la-ligne e

La liste-de-param tres-formels est une liste d'identi cateurs s par s par des virgules. Le e e e reste-de-la-ligne est appel  corps de la macro . Toute occurrence ult rieure de nom sera e e un appel de la macro et devra avoir la forme : nom  liste-de-param tres-e ectifs  e Dans la liste-de-param tres-e ectifs, les param tres sont s par s par des virgules et chaque e e e e param tre est une suite quelconque d'unit s lexicales. Le pr processeur remplace l'ene e e semble nom de la macro et liste de param tres e ectifs parenth s s, par reste-de-la-ligne e ee dans lequel chaque param tre formel est remplac par le param tre e ectif correspondant. e e e Cette op ration de remplacement de texte porte le nom d'expansion de la macro. e L'utilit principale des macros avec param tres est de b n cier de la clart d'exprese e ee e sion des fonctions sans en sou rir la lourdeur : le code est ins r en ligne, donc on conomise ee e le code d'entr e et de retour de fonction. Exemple : e 
define mina, b define maxa, b f int i,j,k; i = minj,k; i = maxj,k; * * e quivalent : i = a e quivalent : i = a j j k k ? ? j k : : k ; j ; * * a a b ? a : b b ? b : a

135

Attention
La distinction entre macro avec et sans param tre se fait sur le caract re qui suit e e imm diatement le nom de la macro : si ce caract re est une parenth se ouvrante c'est une e e e macro avec param tres, sinon c'est une macro sans param tre. En particulier, si apr s le e e e nom de la macro il y a un blanc avant la parenth se ouvrante, a sera une macro sans e c param tre. Exemple : e 
define CARRE a a * a

Une utilisation de CARRE2 aura comme expansion a a * a2 ! Attention donc a l'erreur di cile voir : la pr sence d'un blanc entre le nom d'une macro avec param tres a e e et la parenth se ouvrante. e

Exemple
Cet exemple est tir du source de linux. Il s'agit d'un fragment de gestion de la e m moire virtuelle, une structure page a t d nie : e ee e
struct page struct inode *inode; unsigned long offset; struct page *next_hash; atomic_t count; unsigned flags; * atomic flags, some possibly updated asynchronously * ... * d'autres champs * ;

Dans cette structure, le champs ags est un ensemble de bits d nis ci-apr s : e e
* Page define define define define define define flag bit values * PG_locked PG_error PG_referenced PG_uptodate PG_free_after PG_decr_after 0 1 2 3 4 5

Puis le programmeur a d ni des macros pour tester commod ment ces bits a l'aide de la e e e fonction test bit d nie par ailleurs:
* Make define define define define define define it prettier to test the PageLockedpage PageErrorpage PageReferencedpage PageUptodatepage PageFreeAfterpage PageDecrAfterpage above... * test_bitPG_locked, &page- flags test_bitPG_error, &page- flags test_bitPG_referenced, &page- flags test_bitPG_uptodate, &page- flags test_bitPG_free_after, &page- flags test_bitPG_decr_after, &page- flags

136

Exemple de mauvaise utilisation
Dans une invocation de macro, chaque param tre e ectif peut ^tre une suite quelconque e e d'unit s lexicales, mais apr s expansion, le texte obtenu doit ^tre un fragment valide de e e e langage C. Voici un exemple des horreurs que l'on peut crire en utilisant les macros : e 
define macroa,b a f int i, t 10 ; macrot,i  = 1; * e quivalent t i a = 1; * b

Le second param tre pass a la macro i  ne correspond syntaxiquement rien, mais le e e a r sultat de l'expansion de la macro est correct. e

8.1.4 Les pi ges des macros e

Par le fait que le traitement des macros consiste faire de la substitution de texte, a l' criture de macros rec le de nombreux pi ges. e e e

Pi ges des priorit s d'op rateurs e e e
Supposons que l'on crive : e 
define CARREa a * a

une occurrence de CARREa+b aura comme expansion a+b * a+b ce qui est di rent du e a+b * a+b qui tait d sir . De la m^me mani re !CARREx aura comme expansion e e e e e !x * x ce qui est di rent du !x * x qui tait d sir . e e e e On recommande donc de toujours respecter deux r gles dans la d nition d'une macro e e devant ^tre utilis e dans des expressions : e e 1. parenth ser les occurrences des param tres formels ; e e 2. parenth ser le corps complet de la macro. e Une d nition de CARRE respectant ces r gles est : e e 
define CARREa a * a

Pi ges des e ets de bord e
L'utilisation d'e et de bord sur les param tres e ectifs d'une macro peut avoir des e e ets compl tement inattendus. Apr s la d nition : e e e 
define CARREa a * a

l'utilisation de CARREx++ aura comme expansion x++ donc appliqu deux fois. e 137

* x++,

l'op rateur ++ sera e

Tous les exemples donn s jusqu'ici sont des exemples de macros g n rant des exprese ee sions. Les macros peuvent aussi g n rer des instructions et l aussi il y a des pi ges ee a e a viter. Supposons qu'ayant crire un grand nombre de fois un appel de fonction avec e ae test d'erreur, on d nisse la macro suivante : e 
define Fx if !fx printf"erreur n"; exit1;

8.1.5 Macros g n rant des instructions ee

La macro pourra s'appeler comme une fonction avec un ; la n dans un contexte de a liste d'instructions:
... Fi; ...

Par contre, dans un contexte d'instruction et non de liste d'instructions, il ne faudra pas mettre de ; la n : a
do Fa while  ... ;

alors qu'il le faudrait si il s'agissait d'une fonction :
do fa; while  ... ;

Mais le pire reste venir : voyons ce qui se passe si on utilise la macro F dans un if avec a else :
if  ...  Fi else ...

Il su t d'imaginer l'expansion de la macro :
if  ...  if !fx else ... printf"erreur n"; exit1;

pour comprendre le probl me : le else va ^tre raccroch au if de la macro, ce qui n'est e e e pas ce qu'a voulu le programmeur.

Recommandation
Pour toute macro g n rant des instructions, on recommande d'englober les instructions ee g n r es dans la partie instruction d'un do ... while 0. Notre exemple s' crit ainsi : e ee e 
define Fx do if !fx printf"erreur n"; exit1; while 0

et tous les probl mes pr c dents s' vanouissent. e ee e 138

8.2 Compilation conditionnelle
Les m canismes de compilation conditionnelles ont pour but de compiler ou d'ignorer e des ensembles de lignes, le choix tant bas sur un test ex cut la compilation. e e e ea

8.2.1 Commande if 
if

La commande permettant de r aliser la compilation conditionnelle est la commande e qui peut prendre plusieurs formes.

Commande if simple
Quand le pr processeur rencontre : e if expression ensemble-de-lignes il value expression. Si expression d livre une valeur non nulle, ensemble-de-lignes est e e compil , sinon ensemble-de-lignes est ignor . L' valuation de expression a lieu au moment e e e de la compilation, elle ne doit donc comporter que des constantes. L'ensemble-de-lignes est une suite de lignes quelconques. 
endif

Commande if avec else
Sur rencontre de : if expression ensemble-de-lignes 1 
else

ensemble-de-lignes 2 
endif

le pr processeur value expression. Si expression d livre une valeur non nulle, ensemble-dee e e lignes 1 est compil et ensemble-de-lignes 2 est ignor , sinon ensemble-de-lignes 1 est ignor e e e et ensemble-de-lignes 2 est compil . e

Commande if avec elif
De mani re imbriquer ais ment des if dans des if, il existe une commande elif e a e dont la s mantique est else if. Elle s'utilise de la mani re suivante : e e if expression 1 ensemble-de-lignes 1 elif expression 2 ensemble-de-lignes 2 ... elif expression n ensemble-de-lignes n 
else

ensemble-de-lignes else 
endif

Un seul ensemble-de-lignes sera compil : celui correspondant la premi re expression i qui e a e 139

s' valuera a une valeur non nulle si elle existe, ou bien ensemble-de-lignes else si toutes les e expression i s' valuent 0. e a

8.2.2 Commandes ifdef et ifndef

Dans ce qui pr c de il est possible de remplacer les commandes if expression par : ee ifdef nom ou ifndef nom. Dans ce cas, le test ne porte plus sur la nullit ou non d'une expression, mais sur la e d nition ou non d'une macro. La commande ifdef nom a pour s mantique :  si nom e e est d ni , et ifndef nom a pour s mantique :  si nom n'est pas d ni . e e e

8.2.3 L'op rateur defined e

L'op rateur defined est un op rateur sp cial : il ne peut ^tre utilis que dans le e e e e e contexte d'une commande if ou elif. Il peut ^tre utilis sous l'une des deux formes e e suivantes : defined nom ou bien : defined  nom . Il d livre la valeur 1 si nom est une e macro d nie, et la valeur 0 sinon. L'int r^t de cet op rateur est de permettre d' crire e ee e e des tests portant sur la d nition de plusieurs macros, alors que ifdef ne peut en tester e qu'une. 
if definedSOLARIS || definedSYSV

8.2.4 La commande error

La commande error a la syntaxe suivante : error suite-d-unit s-lexicales e La rencontre de cette commande provoquera l' mission d'un message d'erreur comprenant e la suite-d-unit s-lexicales. Cette commande a pour utilit de capturer la compilation des e e a conditions qui font que le programme ne peut pas s'ex cuter sur cette plate-forme. Voici e un exemple o on teste que la taille des entiers est su sante : u 
include limits.h if INT_MAX 1000000 error "Entiers trop petits sur cette machine" endif

8.2.5 Usage

La compilation conditionnelle a pour but essentiel d'adapter le programme son envia ronnement d'ex cution : soit il s'agit d'un programme syst me devant s'adapter au mat riel e e e sur lequel il s'ex cute, soit il s'agit d'un programme d'application qui doit s'adapter au e syst me sur lequel il s'ex cute. Prenons par exemple le syst me unix qui existe en deux e e e grandes variantes : la variante bsd et la variante system v. La routine de recherche d'un caract re d termin dans une cha^ne s'appelle index en bsd et strchr en system v, e e e
mais l'interface est le m^me. Voici comment on peut crire un programme se compilant et e e s'ex cutant sur les deux plate-formes : le programmeur peut d cider d'utiliser un nom e e a lui, par exemple RechercheCar, et de le d nir comme ci-dessous. e 
if definedHAS_INDEX

140 

define RechercheCar index elif definedHAS_STRCHR define RechercheCar strchr else error "Impossible de r aliser RechercheCar" e endif

Selon le syst me, la compilation se fera par : e
cc -c -DHAS_INDEX fichier.c

ou par :
cc -c -DHAS_STRCHR fichier.c

8.3 R cr ation e e
Quel est le plus petit programme possible en C? Mark Biggar a t un vainqueur de la comp tition du code C le plus obscur ioccc ee e avec un programme ne comportant qu'une seule lettre : P ! Pour arriver ce r sultat, il a e avait compliqu un petit peu la ligne de commande de compilation : e
cc -DC="R 0" -DI="ifTO" -DO="c=write1,&c,1;" -DP="main X " -DR="read0,&c,1" -DT="c!=015" -DW="whileCI" -DX="char c;W" markb.c

Le chier markb.c contenant la lettre P, qui du fait de l'expansion des macros, va ^tre e transform e en : e
main char c; whileread0,&c,1 0 if c!=015 c=write1,&c,1;

141

142

Chapitre 9

Les d clarations e
Nous n'avons vu jusqu' pr sent que des exemples de d clarations, il est temps maina e e tenant de voir les d clarations de mani re plus formelle. e e

9.1 D clarations de d nition et de r f rence e e ee
Il existe dans le langage C, deux types de d clarations : e les d clarations qui d nissent compl tement un objet, ce sont les d clarations de e e e e d nition ; e les d clarations qui font r f rence un objet d ni ailleurs, ce sont les d clarations e ee a e e de r f rence. ee

Les d clarations de d nition e e
Ce sont celles que l'on utilise dans la grande majorit des cas : on d nit un objet et e e ensuite on l'utilise.

Les d clarations de r f rence e ee
Elles sont n cessaires pour : e un nom de variable ou de fonction d ni dans une autre unit de compilation. e e un nom de fonction d ni dans la m^me unit de compilation, pour r soudre le cas e e e e d'appel r cursif : la fonction f1 appelle f2 qui appelle f3, ... qui appelle fn qui appelle e f1. un nom de structure ou d'union d ni dans la m^me unit de compilation, pour e e e r soudre le cas de r f rence r cursive : la struct s1 poss de un champ dont le type e ee e e r f rence la struct s2 qui poss de un champ dont le type r f rence la struct s3 ee e ee qui etc. jusqu' revenir a la struct s1. a 143

9.1.1 D clarations de variables e

Di rences entre d clarations et d nitions de variables : e e e une d claration de r f rence est pr c d e du mot-cl extern ; e ee eee e une d claration de r f rence peut avoir un type incomplet : absence de la taille d'un e ee tableau. Exemples :
int i; extern int j; int t1 20 ; extern t2 ; * * * * d finition de i e r f rence un entier d fini ailleurs e e a e d finition de t e r f rence un tableau t2 d fini ailleurs e e a e * * * *

9.1.2 D clarations de fonctions e

Une d claration de fonction ayant la partie instruction est une d nition, une d e e e claration de fonction n'ayant pas de partie instruction est une d claration de r f rence. e ee La pr sence ou l'absence du mot-cl extern dans l'un ou l'autre cas est possible, mais e e on consid re comme un bon style de programmation de le mettre une d claration de e a e r f rence et de l'omettre une d nition. Exemples : ee a e
* max n'a pas de partie instruction : d claration de r f rence e e e extern int maxint a, int b ; * min poss de la partie instruction : c'est une d finition e e int minint a, int b returna b ? a : b; *

*

9.1.3 D clarations d' tiquettes de structures et union e e

Attention : il ne s'agit pas de d claration de noms de variables de type structure ou e union, mais de d claration d' tiquette de structure ou union. Quand on veut d clarer e e e une tiquette de structure ou union qui sera d nie plus tard, on proc de de la mani re e e e e suivante :
struct str1; struct str2 ... struct str1 * p; ; struct str1 ... struct str2 *p; ; * d finition de str1 qui r f rence str2 e e e * * * d claration de r f rence de str1 e e e d finition de str2 qui r f rence str1 e e e * *

144

Le m canisme est le m^me avec les unions. e e

9.2 Port e des d clarations e e
Il existe en C quatre types de port es possibles pour les d clarations : e e un identi cateur d clar a l'ext rieur de toute fonction, a une port e qui s' tend de e e e e e son point de d claration jusqu' la n du source ; e a un param tre formel de fonction a une port e qui s' tend de son point de d claration e e e e jusqu' la n de l'instruction compos e formant le corps de la fonction ; a e un identi cateur d clar dans une instruction compos e a une port e qui s' tend du e e e e e point de d claration jusqu' la n de l'instruction compos e ; e a e une tiquette d'instruction a une port e qui comprend tout le corps de la fonction e e dans laquelle elle appara^t.
Exemple :
int i; void proc1int j * * d claration l'ext rieur de toute fonction e a e j param tre de la proc dure proc1 e e * *

... k: if ... int l; ... * * * int func1 ... * * *

*

instructions 1

*

d claration l'int rieur d'une instruction compos e e a e e instructions 2 fin de proc1 d but de func1 e instructions 3 fin de func1

* * * * * *

Dans cet exemple, i pourra ^tre r f renc par instructions 1 , instructions 2 et instructions 3 , e ee e j pourra ^tre r f renc par instructions 1 et instructions 2 , e ee e k pourra ^tre r f renc par instructions 1 et instructions 2 , e ee e l pourra ^tre r f renc par instructions 2 . e ee e 145

9.3 Visibilit des identi cateurs e
Dans le langage C, l'imbrication des instructions compos es forme une structure clase sique de blocs, c'est a dire que les d clarations d'une instruction compos e englob e cachent e e e les d clarations des instructions compos es englobantes ayant le m^me nom. De surcro^t, e e e
les d clarations d'une instruction compos e cachent les d clarations de m^me nom, qui e e e e sont l'ext rieur de toute fonction. Exemple : a e
int i; int j; void proc1 int i; int k; if a b * * * cache le i pr c dent e e cache le j pr c dent e e cache le k pr c dent e e * * * * cache le i pr c dent e e *

int i; int j; int k; ...

9.4 Les espaces de noms
9.4.1 Position du probl me e
Il existe certaines situations o l'on peut accepter que le m^me nom d signe plusieurs u e e objets di rents, parce que le contexte d'utilisation du nom permet de d terminer quel est e e l'objet r f renc . Consid rons l'exemple suivant : ee e e
struct st1 int i; int j; ; struct st2 int i; double d; ; int main

146

struct st1 s1; struct st2 s2; s1.i = s2.i;

* *

d claration de la variable s1 e d claration de la variable s2 e

* *

Dans l'instruction s1.i = s2.i, il y a deux occurrence du nom i, la premi re d signe e e le i de s1, et la seconde d signe le i de s2. On voit que le contexte d'utilisation de i a e permis de d terminer a chaque fois de quel i il s'agit. On dit alors que le i de s1 et le i e de s2 appartiennent des espaces de noms di rents. a e

9.4.2 Les espaces de noms du langage C
Il y a quatre types d'espaces de noms dans le langage : un espace pour les tiquettes de structures, d'unions et d' num ration ; e e e un espace pour les noms de champs de structures ou unions : il y a un espace de nom pour chaque structure et chaque union ; un espace pour les tiquettes de branchement ; e le dernier espace est form de tous les autres noms. e Nous donnons ci-dessous un exemple o le m^me identi cateur i est utilis de mani re u e e e valide dans 5 espaces de noms di rents. e
int i; struct i int i; int j; i1,i2; struct ii int i; int j; ii1,ii2; int main i: * i est une tiquette de branchement * e i = 1; i1.i = 2; ii1.i = 3; goto i; * i est un champ de la struct ii * * * * i est un nom d'identificateur i est une tiquette de structure e i est un champ de la struct i * * *

147

Remarque
Certains auteurs consid rent galement qu'il existe un espace de noms pour les noms e e d nis l'aide de la commande define du macro-processeur. Nous avons refus cette e a e vision des choses dans la mesure o pendant la phase de compilation proprement dite, ces u noms n'ont plus d'existence.

9.5 Dur e de vie e
Du point de vue de la dur e de vie, il existe trois types de variables : les variables e statiques, les variables automatiques et les variables dynamiques. Les variables statiques sont allou es au d but de l'ex cution du programme, et ne e e e sont lib r es qu' la n de l'ex cution du programme. ee a e Les variables automatiques sont allou es l'entr e d'une instruction compos e, et e a e e lib r es lors de la sortie de l'instruction compos e. ee e Les variables dynamiques sont allou es et lib r es explicitement par le programmeur, e ee a l'aide des fonctions malloc et free. Dans les langages de programmation, il y a g n ralement un lien troit entre la port e ee e e de la d claration d'une variable et sa dur e de vie. Il est classique en e et, qu'une variable e e globale c'est a dire dont la d claration se trouve l'ext rieur de toute fonction, soit une e a e variable statique, et qu'une variable locale a une proc dure ou fonction, soit une variable e automatique. Dans le langage C, le programmeur a davantage de libert . Les variables globales sont e ici aussi des variables statiques, mais les variables locales peuvent ^tre au choix du proe grammeur statiques ou automatiques. Si la d claration d'une variable locale est pr c d e e eee du mot cl static, cette variable sera statique, si elle est pr c d e du mot-cl auto, elle e eee e sera automatique, et en l'absence de l'un et l'autre de ces mots-cl s, elle sera prise par e d faut de type automatique. e Cette libert de donner une variable locale une dur e de vie gale celle du proe a e e a gramme, permet de r soudre des probl mes du type expos ci-dessous. Imaginons une e e e proc dure qui pour une raison quelconque doit conna^tre combien de fois elle a t appee
ee l e. Le programmeur a besoin d'une variable dont la dur e de vie est sup rieure a celle de e e e la proc dure concern e, ce sera donc une variable statique. Cependant cette variable doit e e ^tre une variable priv e de la proc dure, il n'y a aucune raison qu'une autre proc dure e e e e puisse en modi er la valeur, il faut donc que ce soit une variable locale la proc dure. a e En C, on programmera de la mani re suivante : e

Discussion

148

void proc static int nb_appel = 0; nb_appel++; ...

Dans d'autres langages, de mani re satisfaire les contraintes de dur e de vie, on aurait e a e t oblig de faire de la variable nb_appel, une variable globale, la rendant ainsi accessible ee e aux autres proc dures, ce qui est tout a fait illogique. e

9.6 Classes de m moire e
Lors de l'ex cution d'un programme C il y a trois zones de m moire di rentes, core e e respondant aux trois dur es de vies possibles : e la zone contenant les variables statiques ; la zone contenant les variables automatiques cette zone est g r e en pile puisqu'en ee C, toute fonction peut ^tre r cursive ; e e la zone contenant les variables dynamiques cette zone est g n ralement appel e le ee e tas. Un tel d coupage se rencontre couramment dans les langages de programmation. G e e n ralement cependant, il n'est pas n cessaire au programmeur de d clarer la classe dans e e e laquelle il d sire mettre une variable, cette classe tant choisie de mani re autoritaire par e e e le langage. Les concepteurs du langage C ont voulu o rir plus de souplesse aux programmeurs. En e et, nous venons de voir que l'on pouvait mettre dans la classe des variables statiques une variable qui tait locale une instruction compos e. D'autre part, pour des raisons e a e d'e cacit des programmes g n r s, les concepteurs du langage ont cr une nouvelle e e ee ee classe : la classe register. Quand le programmeur d clare par exemple : e
register int i;

9.6.1 Position du probl me e

ceci est une indication au compilateur, lui permettant d'allouer la variable dans une ressource de la machine dont l'acc s sera plus rapide que l'acc s une m moire si une telle e e a e ressource existe.

149

9.6.2 Les sp ci cateurs de classe de m moire e e

Il existe 5 mots-cl s du langage que la grammaire nomme sp ci cateur de classe de e e m moire. Il s'agit des mots-cl s suivants : e e auto Ce sp ci cateur de classe m moire n'est autoris que pour les variables locales une e e e a instruction compos e. Il indique que la variable concern e une dur e de vie locale e e a e a l'instruction compos e. Si la d claration d'une variable locale ne comporte pas de e e sp ci cateurs de classe de m moire, c'est auto qui est pris par d faut. Exemple : e e e
auto int i; ...

static Ce sp ci cateur de classe m moire est autoris pour les d clarations de variables et e e e e

de fonctions. Pour les d clarations de variables, il indique que la variable concern e e e a une dur e de vie globale. Dans tous les cas, variables et fonctions, il indique que e le nom concern ne doit pas ^tre export par l' diteur de liens. Exemple : e e e e
static int i; int j; static void f static int k; ... * * * * i ne sera pas export par l' diteur de liens e e j sera export par l' diteur de liens e e f ne sera pas export par l' diteur de liens e e k aura une dur e de vie globale e * * * *

void g ...

*

g sera export e par l' diteur de liens e e

*

register Ce sp ci cateur n'est autoris que pour les d clarations de variables locales e e e a

une instruction compos e, et pour les d clarations de param tres de fonctions. Sa e e e signi cation est celle de auto avec en plus une indication pour le compilateur d'allouer pour la variable une ressource acc s rapide. Le programmeur est suppos a e e mettre une variable dans la classe register quand elle est fortement utilis e par e l'algorithme. Il y a cependant une contrainte : une telle variable n'a pas d'adresse, impossible donc de lui appliquer l'op rateur &. e extern Ce sp ci cateur est autoris pour les d clarations de variables et de fonctions. Il e e e sert a indiquer que l'objet concern a une dur e de vie globale et que son nom est e e connu de l' diteur de liens. e typedef Ce sp ci cateur n'a rien a voir avec les classes de m moire : il sert d nir des e e a e types. Son utilit sera vue plus loin. e 150

Discussion
On peut faire les critiques suivantes : 1. 2. ne peut servir que pour les variables locales, mais si on ne le met pas, il est pris par d faut. Conclusion : il ne sert a rien. e
auto

sert deux choses tr s di rentes : il permet de rendre statique une variable a e e locale, et c'est une utilisation l gitime, mais il sert aussi cacher a l' diteur de liens e a e les variables globales. On rappelle que par d faut c'est dire sans le mot-cl static, e a e les variables globales sont connues de l' diteur de liens. Il aurait mieux valu e faire l'inverse : que par d faut les variables globales soient cach es a l' diteur de liens, e e e et avoir un mot-cl par exemple export, pour les lui faire conna^tre. e

static register a t introduit dans le langage pour optimiser les programmes. Avec les ee techniques modernes de compilation, il ne sert a rien car le compilateur est mieux a m^me que le programmeur d'allouer les registres de la machine de mani re e cace. e e Ne pas oublier en outre, qu'il y a une contrainte attach e l'utilisation de variables e a register : l'impossibilit de leur appliquer l'op rateur &. e e extern et typedef n'ont rien voir avec les classes de m moire : ils ne sont l que a e a pour des raisons syntaxiques.

3.

4.

9.7 La compilation s par e e e
9.7.1 G n ralit s ee e
D s que l'on programme une application un peu cons quente, il devient n cessaire pour e e e des raisons pratiques d'en fractionner le source en plusieurs unit s de compilation. Chaque e unit est compil e s par ment, puis les binaires obtenus sont li s a l'aide d'un diteur de e e e e e e liens pour cr er le programme d sir . Pour permettre cela, le langage doit disposer d'un e e e moyen d'exprimer que certaines variables ou proc dures sont partag es par plusieurs unit s e e e de compilation. La m thode la plus r pandue pour r soudre ce probl me est la m thode e e e e e dite  des r fs et des d fs . Pour le seul cas des variables, il existe une autre m thode dite e e e  du common  .  

M thode des r fs et des d fs e e e
Dans cette m thode les d clarations sont dissym triques : certaines d clarations sont e e e e des d nitions, et d'autres d clarations sont des r f rences. Une seule unit de compilation e e ee e doit d nir un nom, et plusieurs unit s de compilation peuvent le r f rencer. e e ee

M thode du common e
Dans cette m thode, les variables partag es sont d clar es comme appartenant un e e e e a segment sp cial, appel common. Toute variable du common est r f renable par n'importe e e ee c quelle unit de compilation. C'est la m thode utilis e par fortran. e e e 151

9.7.2 La m thode du langage C e
C'est un joyeux m lange des deux ! En e et, le langage permet de d nir, r f rencer et e e ee mettre dans le common. La distinction entre ces trois cas se fait de la mani re suivante : e Si la d claration e Il s'agit d'une comporte un initialisateur avec ou sans mot-cl extern e d nition e comporte le mot-cl extern mais pas d'initialisateur e r f rence ee ne comporte ni initialisateur ni le mot-cl extern e mise dans le common Exemples :
extern int i = 1; int i = 1; extern int i; int i;

La d claration e

est une d nition e d nition e r f rence ee mise dans le common

Les contraintes
Au moment de l' dition de liens, pour un identi cateur donn , n unit s de compilation e e e l'auront d ni, p l'auront r f renc , et q auront demand une mise dans le common. Les e ee e e contraintes sont les suivantes :
n doit valoir 0 ou 1 : au plus une unit de compilation doit d nir un nom ; e e

si n vaut 0, alors q ne peut ^tre nul : il ne peut pas y avoir que des r f rences. e ee Voyons les choses sous l'angle de ce qui est autoris . On peut avoir : e une d nition avec p  vent. 0 r f rences, et q  vent. 0 demandes de mise dans le e e ee e common ;
p  vent. 0 r f rences et q non 0 demandes de mise dans le common. e ee

Ceci fait beaucoup de possibilit s dont deux seulement sont  raisonnables  : e une d nition avec que des r f rences : on adh re strictement la m thode des r fs e ee e a e e et des d fs ; e que des demandes de mise dans le common : on adh re strictement la m thode du e a e common. Ces deux m thodes sont r sum es dans le tableau suivant : e e e m thode unit de compilation 1 unit de compilation 2 ... unit de compilation n e e e e r fs d fs e e int i = 0; extern int i; ... extern int i common int i ; int i ; ... int i ; 152

En pratique
Les bons auteurs recommandent de s'en tenir a la stricte m thode des r fs et d fs, mais e e e la lecture de nombreux sources montre que c'est la m thode du common qui a la faveur des e programmeurs. Cette m thode en e et un avantage pratique : dans toutes les unit s de e a e compilations, la d claration d'un nom est strictement la m^me. Cette d claration pourra e e e donc ^tre mise dans un chier qui sera inclus par include dans toutes les unit s de e e compilation qui utilisent ce nom. La m thode des r fs et des d fs par contre, impose d'avoir au moins deux d clarations e e e e di rentes pour un m^me nom : une pour la d nition et une autre qui peut ^tre dans un e e e e chier d'inclusion pour la r f rence. ee

Le cas des fonctions
Le cas des fonctions est plus simple dans la mesure o il n'y a pas de mise dans le u common. Les fonctions adh rent donc strictement la m thode des r fs et des d fs, avec e a e e e une distinction facile faire : comme on l'a vu en 9.1.2, si une d claration de fonction a e comporte une partie instruction c'est une d nition, sinon c'est une r f rence. e ee

9.8 D nition de types e
Il existe en C un moyen de donner un nom a un type. Il consiste faire suivre le mot a cl typedef d'une construction ayant exactement la m^me syntaxe qu'une d claration de e e e variable. L'identi cateur qui est le nom de la variable dans le cas d'une d claration de e variable, est le nom du type dans le cas d'un typedef. Exemple :
typedef int tab 10 ;

d clare tab comme tant le type tableau de 10 entiers, et : e e
typedef struct char nom 20 ; int no_ss; personne;

d clare personne comme tant le type structure a deux champs : un tableau de 20 carace e t res et un int. Ces noms de type sont ensuite utilisables dans les d clarations de variables, e e exactement comme un type de base :
tab t1,t2; personne *p1,*p2; * * t1 et t2 tableaux de 10 entiers p1 et p2 pointeurs vers des struct * *

9.9 Utilit des typedef e
La principale utilit des typedef est, si l'on en fait une utilisation judicieuse, de faciliter e l' criture des programmes, et d'en augmenter la lisibilit . e e 153

9.9.1 Restriction d'un type de base

Il est parfois n cessaire de manipuler des variables qui ne peuvent prendre comme e valeurs qu'un sous-ensemble des valeurs d'un type de base. Supposons que nous voulions manipuler des bool ens. Comme le type bool en n'existe pas dans le langage, il faudra e e utiliser des int, en se restreignant a deux valeurs, par exemple 0 et 1. Il est alors int ressant e de red nir l'aide d'un typedef, le type int. On crira par exemple : e a e 
define VRAI 1 define FAUX 0 typedef int BOOLEAN;

On pourra par la suite d clarer des  bool ens  de la mani re suivante : e e e
BOOLEAN b1,b2;

et les utiliser :
b1 = VRAI; if b2 == FAUX ...

mais bien entendu, ce sera la charge du programmeur d'assurer que les variables b1 et a b2 ne prennent comme valeurs que VRAI ou FAUX. Le compilateur ne protestera pas si on crit : e
b1 = 10;

On voit que la lisibilit du programme aura t augment e, dans la mesure o le programe ee e u meur aura pu expliciter une restriction s mantique apport e au type int. e e

9.9.2 D nition de type structure e
struct personne ...

Lorsqu'on donne un nom a un type structure par typedef, l'utilisation est beaucoup plus ais e. En e et, si on d clare : e e

les d clarations de variables se feront par : e
struct personne p1,p2;

alors que si on d clare : e
typedef struct ... PERSONNE;

154

les d clarations de variables se feront par : e
PERSONNE p1,p2;

on voit que la seconde m thode permet d' viter d'avoir r p ter struct. e e a ee De la m^me mani re, en ce qui concerne les pointeurs, il est plus di cile d' crire et de e e e comprendre :
struct personne ... ; struct personne *p1,*p2;

*

p1 et p2 pointeurs vers des struct

*

que la version suivante qui donne un nom parlant au type pointeur vers struct :
typedef struct ... PERSONNE; typedef PERSONNE *P_PERSONNE; P_PERSONNE p1,p2; * * P_PERSONNE type pointeur vers struct * p1 et p2 pointeurs vers des struct *

9.9.3 D nition de types opaques e
Dans le cadre de l' criture de programme en plusieurs unit s de compilation, il est e e souvent utile de d nir un type de mani re opaque, c'est dire d'en laisser libre l'utilisation e e a sans que l'utilisateur n'ait conna^tre sa d nition. C'est exactement ce que r alise la a
e e biblioth que standard pour le type FILE : le programmeur sait que fopen rend une e valeur de type FILE * et que cette valeur doit ^tre pass e en param tre des fonctions e e e d'entr es-sorties fprintf, fputc, fputs etc. Il y a beaucoup d'autres exemples de e ce type dans la biblioth que standard. e

9.10 Quali catifs de type
Il y a deux faons possibles de quali er un type : par const ou par volatile. c

Quali catif const
Une variable dont le type est quali e par const ne peut pas ^tre modi e. Le proe e e grammeur entend ainsi se prot ger contre une erreur de programmation. Ceci n'est utile e que pour les param tres d'une fonction, lorsqu'on d sire prot ger le param tres e ectifs e e e e de la fonction en les mettant en  lecture seulement  pour la fonction. 155

Quali catif volatile
En quali ant par volatile le type d'une variable, le programmeur pr vient le compie lateur que cette variable peut ^tre modi e par un moyen ext rieur au programme. Ceci se e e e produit lorsqu'on interagit avec des parties mat rielles de la machine : coupleurs d'entr ese e sorties g n ralement. Lorsqu'une variable est de type volatile le compilateur ne doit pas ee proc der aux optimisations qu'il r alise sur les variables normales. e e Les quali catifs de type deviennent p nibles en conjonction avec les pointeurs car on e a les trois possibilit s: e l'objet point est quali ; e e le pointeur lui-m^me est quali ; e e le pointeur et l'objet point sont quali s. e e type
const char c; const char *p; char * const p; const char * const p;

s mantique e caract re constant e pointeur vers caract re constant e pointeur constant vers caract re e pointeur constant vers caract re constant e

9.11 Fonction nombre variable de param tres a e
Il est possible de d clarer une fonction comme ayant un nombre variable de param tres e e en  d clarant  les param tres optionnels par l'unit lexicale ... 3 points la suite. e e e a Une fonction peut avoir a la fois des param tres obligatoires et des param tres optionnels, e e les param tres obligatoires apparaissant en premier et l'unit lexicale ... apparaissant en e e derni re position dans la liste de d claration des param tres formels. e e e Dans le corps de la fonction on ne dispose pas de nom pour d signer les param tres. e e L'acc s ceux-ci ne peut se faire qu'en utilisant les macros suivantes d nies dans la e a e biblioth que standard : e
va list

permet de d clarer une variable opaque au programmeur, passer en param tre e a e aux autres macros. Cette variable s'appelle traditionnellement ap pour argument pointer, et a pour but de rep rer le param tre e ectif courant. e e

va start

doit ^tre appel e avant toute utilisation de va arg. La macro va start a deux e e param tres : la variable ap et le nom du dernier param tre obligatoire de la fonction. e e d livre le param tre e ectif courant : le premier appel a va arg d livre le premier e e e param tre, puis chaque nouvel appel va arg d livre le param tre suivant. La macro e a e e va arg admet deux param tres : la variable ap et le type du param tre courant. e e doit ^tre appel e apr s toutes les utilisations de va arg. La macro va end admet e e e un seul param tre : la variable ap. e

va arg

va end

Rien n'est pr vu pour communiquer la fonction le nombre et le type des param tres e a e e ectivement pass s : c'est un probl me la charge du programmeur. e e a 156

9.11.1 Exemple 1

Ci-dessous l'exemple de la fonction addn qui r alise la somme de ses param tres ope e tionnels. 
include stdio.h include stdarg.h ***************************************************************************** * * * addn * * * * But: * * r alise l'addition d'un nombre variable de param tres e e * * * ***************************************************************************** int addnint nbopd, ... * nbopd = nombre d'op randes du add e * int i, s = 0; va_listap; va_startap,nbopd; for i = 1; i = nbopd; i++ s = s + va_argap,int; va_endap; returns;

* * * *

d claration de ap e initialisation de ap va_arg donne le param tre courant e on a fini

* * * *

***************************************************************************** * main * ***************************************************************************** int main printf"resu = d n",addn3,10,11,12; * imprime 33 *

Dans cet exemple, le probl me du nombre de param tres e ectifs a t r gl par un parae e ee e e m tre obligatoire de la fonction : nbopd. En ce qui concerne le type des param tres e ectifs, e e ils sont tous suppos s ^tre entiers, d'o le va argap,int. e e u

9.11.2 Exemple 2

Dans la biblioth que standard, il y a deux fonctions utilis es couramment qui ade e mettent un nombre variable de param tres : ce sont printf et scanf. Voici leur d claration e e dans stdio.h :
extern int printfconst char *, ...; extern int scanfconst char *, ...;

Ces fonctions doivent conna^tre le nombre et le type des param tres optionnels. Ce pro
e bl me est r gl par les s quences d' chappement se trouvant dans le param tre obligatoire : e e e e e e le nombre de param tres optionnels est gal au nombre de s quences d' chappement ; e e e e le type de chaque param tre optionnel est cod dans sa s quence chappement : c e e e e pour char, d pour int, etc. 157

9.12 Syntaxe des d clarations e
La grammaire des d clarations est la suivante : e
d claration : e  sp ci cateurs-de-d claration liste-de-d clarateurs-init option e e e
;

sp ci cateurs-de-d claration : e e  sp ci cateur-de-classe-m moire sp ci cateurs-de-d claration option e e e e  sp ci cateur-de-type sp ci cateurs-de-d claration option e e e  quali catif-de-type sp ci cateurs-de-d claration option e e liste-de-d clarateurs-init : e  d clarateur-init e  liste-de-d clarateurs-init e d clarateur-init : e  d clarateur e  d clarateur e d clarateur-init e

,

=

initialisateur

sp ci cateur-de-classe-m moire : e e 

   

auto extern static register typedef

sp ci cateur-de-type : e 

void  char  short  int  long  float  double  signed  unsigned  sp ci cateur-de-struct-ou-union e  sp ci cateur-d- num ration e e e  nom-de-typedef
liste-de-d clarations-de-struct e

sp ci cateur-de-struct-ou-union : e  struct-ou-union identi cateur option  struct-ou-union identi cateur struct-ou-union : 

struct

158 

union

liste-de-d clarations-de-struct : e  d claration-de-struct e  liste-de-d clarations-de-struct d claration-de-struct e e d claration-de-struct : e  liste-de-sp ci cateurs-et-quali catifs liste-de-d clarateurs-de-struct e e liste-de-sp ci cateurs-et-quali catifs : e  sp ci cateur-de-type liste-de-sp ci cateurs-et-quali catifs option e e  quali catif-de-type liste-de-sp ci cateurs-et-quali catifs option e liste-de-d clarateurs-de-struct : e  d clarateur-de-struct e  liste-de-d clarateurs-de-struct e d clarateur-de-struct : e  d clarateur e  d clarateur option e d clarateur-de-struct e
;

,

:

expression-constante liste-d- num rateurs e e

sp ci cateur-d- num ration : e e e  enum identi cateur option  enum identi cateur liste-d- num rateurs : e e  num rateur e e  liste-d- num rateurs e e num rateur : e e  identi cateur  identi cateur quali catif-de-type :

,

num rateur e e

=

expression constante 



const volatile

d clarateur : e  pointeur option d clarateur-direct e d clarateur-direct : e  identi cateur   d clarateur  e  d clarateur-direct e  d clarateur-direct e  d clarateur-direct e 



expression-constante option liste-de-types-de-param tres e liste-d-identi cateurs option 



159

pointeur : 



* *

liste-de-quali catifs-de-types option liste-de-quali catifs-de-types option pointeur

liste-de-quali catifs-de-types :  quali catif-de-type  liste-de-quali catifs-de-types quali catif-de-type liste-de-types-de-param tres : e  liste-de-param tres e  liste-de-param tres e

,

...

liste-de-param tres : e  d claration-de-param tre e e  liste-de-param tres , d claration-de-param tre e e e d claration-de-param tre : e e  sp ci cateurs-de-d claration d clarateur e e e  sp ci cateurs-de-d claration d clarateur-abstrait option e e e liste-d'identi cateurs :  identi cateur  liste-d'identi cateurs identi cateur

,

initialisateur :  expression-d'a ectation  liste-d-initialisateurs  liste-d-initialisateurs liste-d'initialisateurs :  initialisateur  liste-d'initialisateurs

,

,

initialisateur

Exemples
Dans la d claration : e
int i,j = 2;

est un sp ci cateur-de-type et i,j = 2 est une liste-de-d clarateur-init compos e de e e e deux d clarateur-init : i et j = 2. i est un d clarateur-init sans la partie initialisateur, donc e e r duit un d clarateur lui-m^me r duit a un identi cateur. j = 2 est un d clarateur-init e a e e e e comportant un initialisateur = 2 et un d clarateur r duit un identi cateur j. Dans e e a la d claration : e
int int t 10 ;

160

est un d clarateur form d'un d clarateur t, suivi de e e e constante 10, suivi de .
t 10

suivi de l'expression

9.13 S mantique des d clarations e e
La partie qui n cessite d'^tre explicit e est la partie de la grammaire concernant les e e e d clarateur. La s mantique est la suivante : e e la seule r gle de la grammaire qui d rive vers un terminal est la r gle : e e e d clarateur-direct : e  identi cateur ce qui fait qu'a l'int rieur de tout d clarateur se trouve un identi cateur. Cet idene e ti cateur est le nom de l'objet d clar par la d claration. Exemple : e e e
char c; * d claration de la variable c de type char e *

il y a 3 constructeurs de type : 1. * est un constructeur permettant de construire des types  pointeur vers ... . Exemple :
* d claration de p de type pointeur vers short int e short int *p; *

2. 



est un constructeur permettant permettant de construire des types  fonction retournant ... . Exemple :
* d claration de sin de type fonction retournant un double e double sin; *

3. expression-constante option est un constructeur permettant de construire des types  tableau de ... . Exemple :
* d claration de t de type tableau de 32 int e int t 32 ; *

les constructeurs de type peuvent se composer et sont a ect s de priorit s. Les e e constructeurs   et ont la m^me priorit , et celle-ci est sup rieure a la priorit e e e e du constructeur *.
char *t 10 ; int *f; double t 10 10 ; * * * tableau de 10 pointeurs vers des char fonction retournant un pointeur vers un int tableau de 10 tableaux de 10 double * * *

tout comme avec des expressions, la r gle : e d clarateur-direct : e   d clarateur  e permet de parenth ser des d clarateur de mani re a en changer la s mantique : e e e e
char *t 10 ; char *t 10 ; * * tableau de 10 pointeurs vers un char pointeur vers un tableau de 10 char * *

161

9.14 Discussion sur les d clarations e
La syntaxe et la s mantique des d clarations ne sont pas faciles a appr hender dans le e e e langage C pour les raisons que nous allons d velopper. Tout d'abord, l'ordre des l ments e ee d'une d claration est assez peu naturel. Au lieu d'avoir comme en pascal, une d claration e e
c : char;

qu'on peut traduire par  c est de type char , on a en C :
char c;

qu'il faut traduire par  de type char est c , ce qui est une inversion peu naturelle. Ensuite, l'identi cateur qui est le nom de l'objet d clar , au lieu d'^tre mis en vidence dans la e e e e d claration, est cach au beau milieu du d clarateur. Exemple : e e e
char **p 10 ;

D'autre part, le langage C fait partie des langages qui permettent au programmeur, a partir de types de base et de constructeurs de type, de construire des types complexes. Du point de vue du programmeur, il existe dans le langage les constructeurs suivants :
*

pour les pointeurs ; pour les tableaux ; pour les fonctions ; pour les structures ; pour les unions. 



struct union

Alors que le programmeur serait en droit de s'attendre ce que tous ces constructeurs a soient trait s de mani re homog ne, en fait, les trois premiers sont des d clarateur alors e e e e que les deux derniers sont des sp ci cateur-de-type. e Autre point ajoutant encore a la confusion, le constructeur * est un constructeur pr x e e alors que les constructeurs et   sont post x , et le constructeur * a une priorit e e di rente de celle des deux autres. Ceci a la cons quence extr^mement d sagr able, qu'un e e e e e type complexe crit en C ne peut pas se lire de la gauche vers la droite, mais peut n cessiter e e un analyse du type de celle que l'on fait pour comprendre une expression math matique. e Par exemple, qui pourrait dire du premier coup d' il quel est le type de f dans la d claration ci-dessous 1 : e
char **f 

1. f est une fonction retournant un pointeur vers un tableau de pointeurs vers une fonction retournant un char

162

9.15 En pratique
Lorsqu'il s'agit d' crire ou de comprendre un type compliqu , il est recommand non e e e pas d'utiliser la grammaire des d clarateur, mais de partir d'une utilisation du type, e tant donn que la grammaire est faite de telle sorte que les d clarations calquent tr s e e e e exactement les expressions. Voyons sur un exemple. Soit d clarer un pointeur p vers une fonction retournant a e un int. Consid rons l'utilisation de p : partir de p, il faut d'abord utiliser l'op rateur e a e indirection pour obtenir la fonction, soit *p. Ensuite, on va appeler la fonction d livr e par e e l'expression *p, pour cela il faut crire *p 2. Finalement cette expression nous d livre e e un int. La d claration de p s' crira donc : e e
int *p;

De la m^me mani re, pour interpr ter un type compliqu , il vaut mieux partir d'une e e e e utilisation. Soit interpr ter : a e
char *f ;

Imaginons une utilisation: *fi j . L'op rateur appel de fonction tant plus priorie e taire que l'op rateur indirection, on applique d'abord l'appel de fonction f. Donc f est e a une fonction. Ensuite on applique l'op rateur indirection, donc f est une fonction retoure nant un pointeur. On indexe le r sultat, donc f est une fonction retournant un pointeur e vers un tableau. Finalement, on voit que f est une fonction retournant un pointeur vers un tableau de char.

9.16 Un outil : cdecl
Il existe dans le domaine public un petit outil pour manipuler les d clarations du e langage C : cdecl. On peut le trouver facilement sur Internet en utilisant xarchie. Ce programme a t crit initialement pour hpux, on le trouve donc g n ralement class dans eee ee e les archives concernant ce syst me, 3 mais il est facilement portable sur une autre platee forme. Le programme cdecl peut traduire une d claration C en pseudo-anglais commande e explain et vice-versa commande declare. Exemple d'interaction :
osiris1 cdecl Type `help' or `?' for help cdecl explain char * argv declare argv as array of pointer to char cdecl declare p as pointer to function returning int int *p cdecl  appel de cdecl 

  

la question la r ponse e la question la r ponse e

2. A l'utilisation il faudra mettre les param tres e ectifs e 3. En juillet 96, on peut le trouver sur hpftp.cict.fr: hpux

Misc cdecl-1.0

163

164

Chapitre 10

La biblioth que standard e
Ce chapitre est un aide-m moire ; il donne la liste exhaustive de toutes les fonctions de e la biblioth que standard, sans donner la s mantique pr cise de ces fonctions. Pour obtenir e e e plus d'information, utiliser la commande man sur une machine unix.

10.1 Diagnostic
La fonction assert permet de mettre des assertions dans le source du programme. A l'ex cution, si le param tre de assert s' value faux, le programme est stopp sur e e e a e terminaison anormale.

10.2 Manipulation de caract res e
fonction

ctype.h

Toutes les fonctions ci-dessous permettent de tester une propri t du caract re pass ee e e en param tre. e
isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit

le param tre est e une lettre ou un chi re une lettre un caract re de commande e un chi re d cimal e un caract re imprimable ou le blanc e une lettre minuscule un caract re imprimable pas le blanc e un caract re imprimable pas isalnum e un caract re d'espace blanc e une lettre majuscule un chi re hexad cimal e

On dispose galement de deux fonctions de conversions entre majuscules et minuscules : e
tolower : toupper :

conversion en minuscule ; conversion en majuscule. 165

10.3 Environnement local

locale.h

Il y a deux fonctions permettant de g rer les conventions nationales concernant l' crie e ture du point d cimal dans les nombres, le signe repr sentant l'unit mon taire etc. Ces e e e e fonctions sont setlocale et localeconv.

10.4 Math matiques e

math.h

10.4.1 Fonctions trigonom triques et hyperboliques e
e fonction s mantique acos arc cosinus asin arc sinus arc tangente atan atan2 arc tangente cosinus cos cosh cosinus hyperbolique sin sinus hyperbolique sinus sinh tan tangente tanh tangente hyperbolique

10.4.2 Fonctions exponentielles et logarithmiques
x n p

fonction s mantique e exp exponentielle frexp tant donn , trouve et tels que =  2p e e ldexp multiplie un nombre par une puissance enti re de 2 e log logarithme logarithme d cimal e log10 modf calcule partie enti re et d cimale d'un nombre e e
x n

10.4.3 Fonctions diverses

fonction s mantique e ceil entier le plus proche par les valeurs sup rieures e fabs valeur absolue floor entier le plus proche par les valeurs inf rieures e reste de division fmod pow puissance sqrt racine carr e e
setjmp.h

10.5 Branchements non locaux

L'instruction goto qui ne avons vu au paragraphe 3.15.2 ne permet de r aliser des brane chements qu'au sein d'une m^me proc dure. Pour r aliser des branchements a l'ext rieur e e e e d'une proc dure, il faut utiliser setjmp et longjmp. e 166

10.6 Manipulation des signaux
signal raise

signal.h

Deux fonctions permettent d'interagir avec le m canisme des signaux : e permet d'installer une fonction qui sera ex cut e sur r ception d'un signal ; e e e

d clenche un signal chez le processus ex cutant. e e
stdarg.h

10.7 Nombre variable de param tres e

Si on d sire programmer une fonction avec un nombre variable de param tres, on e e dispose de trois macros : va_start, va_arg et va_end.

10.8 Entr es sorties e

stdio.h

10.8.1 Op rations sur les chiers e
fonction description remove destruction de chier rename modi cation de nom de chier tmpfile cr ation d'un chier temporaire e tmpnam g n ration de nom appropri pour un chier temporaire ee e

10.8.2 Acc s aux chiers e
fclose fflush fopen freopen

fonction description fermeture de chier criture sur chier des bu ers en m moire e e ouverture de chier ouverture de chier

10.8.3 Entr es-sorties formatt es e e
fonction
fprintf fscanf printf scanf sprintf sscanf vfprintf vprintf vsprintf

description criture formatt e sur ot de donn es e e e lecture formatt e sur ot de donn es e e criture formatt e sur sortie standard e e lecture formatt e sur entr e standard e e criture formatt e dans une cha^ne de caract res e e
e lecture formatt e depuis une cha^ne de caract res e
e variante de fprintf variante de printf variante de sprintf 167

10.8.4 Entr es-sorties caract res e e

fonction description fgetc lecture d'un caract re e fgets lecture d'une cha^ne de caract res
e fputc criture d'un caract re e e fputs criture d'une cha^ne de caract res e
e getc fgetc impl ment par une macro e e getchar getc sur l'entr e standard e gets lecture d'une cha^ne de caract res sur l'entr e standard
e e putc fputc impl ment par une macro e e putchar putc sur la sortie standard puts criture d'une cha^ne de caract res sur la sortie standard e
e refoule un caract re sera lu par la prochain lecture e ungetc

10.8.5 Entr es-sorties binaires e

Pour lire et crire des donn es binaires, on dispose de deux fonctions : fread et fwrite. e e fonction description fgetpos donne la position courante dans un chier fseek permet de se positionner dans un chier fsetpos permet de se positionner dans un chier ftell donne la position courante dans un chier rewind permet de se positionner au d but d'un chier e description remet faux les indicateurs d'erreur et de n de chier a test de l'indicateur de n de chier test de l'indicateur d'erreur imprime un message d'erreur correspondant errno a
stdlib.h

10.8.6 Position dans un chier

10.8.7 Gestion des erreurs
clearerr feof ferror perror

fonction

10.9 Utilitaires divers

10.9.1 Conversion de nombres

Les fonctions suivantes permettent de convertir des nombres entre la forme cha^ne de
caract res et la forme binaire. e fonction description atof conversion de cha^ne vers double
atoi conversion de cha^ne vers int
conversion de cha^ne vers long int
atol strtod conversion de cha^ne vers double
conversion de cha^ne vers long int
strtol strtoul conversion de cha^ne vers unsigned long int
168

10.9.2 G n ration de nombres pseudo-al atoires ee e
On dispose de rand et srand.

10.9.3 gestion de la m moire e
free, malloc

Trois de ces fonctions ont t vues au paragraphe 6.11. La liste exhaustive est calloc, ee et realloc.

10.9.4 Communication avec l'environnement
fonction description abort terminaison anormale du programme atexit installe une fonction qui sera ex cut e sur terminaison normale du programme e e obtention d'une variable d'environnement getenv system ex cution d'un programme e

10.9.5 Recherche et tri

Deux fonctions : bsearch et qsort. fonction description abs valeur absolue div obtention de quotient et reste labs idem abs sur des long int

10.9.6 Arithm tique sur les entiers e

10.9.7 Gestion des caract res multi-octets e

Les caract res multi-octets permettent de prendre en compte les langues qui ne peuvent e se satisfaire de caract res cod s sur 8 bits. La liste exhaustive des fonctions est : mblen, e e mbtowc, wctomb, mbstowcs, wcstombs.

10.10 Manipulation de cha^nes

string.h

On dispose de fonctions pour : copier : memcpy, memmove, strcpy, strncpy ; concat ner : strcat, strncat ; e comparer : memcmp, strcmp, strcoll, strncmp ; transformer : strxfrm ; rechercher : memchr, strchr, strcspn, strpbrk, strrchr, strspn, strstr, strtok ; initialiser: memset ; calculer une longueur : strlen ; 169

obtenir un message d'erreur a partir du num ro de l'erreur : strerror. e

10.11 Manipulation de la date et de l'heure
time, asctime, ctime, gmtime, localtime, strftime.

time.h

Les fonctions de manipulation de la date et de l'heure sont : clock, difftime, mktime,

170

Annexe A

Les jeux de caract res e
Un jeu de caract re est un ensemble de signes typographiques et un codage : chaque e a signe est associ un nombre entier qui est son code. e

A.1 Les normes
L'histoire des jeux de caract res pour les besoins de l'informatique d bute avec le e e codage ebcdic sur 8 bits utilis par ibm et le codage ascii sur 7 bits utilis par le e e reste du monde. Le code ebcdic n'est pas une norme, mais le code ascii est une norme de l'ansi. En 1963, l'iso cr e une norme internationale partir de la norme ascii et, internatioe a nalisation oblige, elle r serve 10 caract res pour des variantes nationales. La France dans e e une norme nf en utilisera 5 pour y caser des lettres accentu es   u laissant de c^t e acee oe l'accent circon exe si cher aux acad miciens franais, le tr ma et les ligatures. Cette norme e c e est donc inutilisable pour crire r ellement en franais, mais il faut dire la d charge de e e c a e l'iso, qu'en utilisant un code 7 bits, cela tait impossible. a e En 1988, l'iso dite une nouvelle norme de jeu de caract res 8 bits cette fois pour e e a prendre en compte les particularit s des langues europ ennes. Mais la diversit est telle e e e qu'il n'est pas possible de mettre tous les signes typographiques dans un seul jeu de 256 caract res. Les langues ont donc t regroup es en familles, et la norme iso-8859 comprend e ee e plusieurs jeux de caract res. Celui qui nous int resse est celui qui est pr vu pour les langues e e e d'europe occidentale et qui est r f renc iso-8859-1 ou iso-latin-1. Malheureusement, les ee e franais ne sont pas de tr s bons lobbyistes dans les instances internationales, et aussi c e incroyable que cela puisse para^tre, la ligature du franais a t oubli e !
c ee e

Pour en savoir plus
Il existe un excellent article de Jacques Andr et Michel Goosens sur les probl mes de e e normalisation de codage de caract res, librement accessible via l'url : e http: www.univ-rennes1.fr pub gut publications . Il s'agit de la revue  les cahiers  de GUTenberg  , et l'article en question est dans le cahier 20. Pour le probl me de la e ligature , voir le cahier 25. 171

A.2 Le code ascii
Le jeu de caract res est form d'un ensemble de caract res de commandes et de carace e e t res graphiques. L'ensemble des caract res de commande est form de six familles : e e e commandes de format commande carriage return line feed backspace horizontal tabulation vertical tabulation space form feed nom CR LF BS HT VT SP FF

Le nom carriage return arrive tout droit de l' poque des machines crire, o la e ae u position d' criture tait xe et o le papier tait port sur un chariot carriage e e u e e mobile. Le caract re carriage return est la commande permettant de mettre la poe sition d' criture en d but de ligne, sans changer de ligne. Le caract re line feed met e e e la position d' criture sur la ligne suivante, sans aller en d but de ligne. Pour obtee e nir l'e et de  passage la ligne  , il faut donc un caract re carriage return suivi a e d'un caract re line feed ou l'inverse. Dans le syst me unix, le caract re choisi par e e e convention comme signi ant  passage la ligne  est le caract re line feed, et c'est a a e la charge des pilotes de p riph riques de remplacer ce caract re logique par la suite e e e de caract res n cessaires pour obtenir un passage la ligne suivante. Prenons le cas e e a d'un pilote de terminal cran clavier : e en entr e : la convention habituelle est de faire un passage la ligne an appuyant e a sur la touche carriage return. Le pilote de terminal : 1. envoie au programme qui r alise la lecture un line feed. e 2. envoie l' cran en tant qu' cho de ce carriage return la s quence line feed a e e e suivi de carriage return. en sortie : le pilote de terminal transforme les line feed en line feed suivi de carriage return Par abus de langage, dans le monde C et ou unix, on utilise souvent le terme de newline pour d signer en r alit line feed. Mais qu'il soit bien clair que la norme e e e ansi ne comporte pas de caract re appel newline. e e commandes d'extension du code commande nom shift out SO shift in SI escape ESC Le caract re escape a t largement utilis par les concepteurs de terminaux crane ee e e clavier et d'imprimantes pour augmenter le nombre de commandes. La technique 172

consiste d nir des s quences d' chappement form es du caract re escape suivi d'un a e e e e e certains nombre de caract res ordinaires qui perdent leur signi cation habituelle. e Voici quelques s quences d' chappement du terminal cran-clavier vt100 : e e e s quence e escape 2A escape 4B escape 3C escape 1D commande de s paration e commande nom le separator FS group separator GS record separator RS unit separator US end of medium EM Ces caract res ont pour but de s parer les di rentes unit s d'information sur bandes e e e e magn tiques. Ils sont obsol tes de nos jours, les programmes d'archivage tar, cpio e e utilisant leur propre format sans faire appel a ces caract res. e commandes pour la communication synchrone commande start of header start of text end of text end of transmission end of transmitted block enquiry positive acknowledge negative acknowledge synchronisation data link escape null nom SOH STX ETX EOT ETB ENQ ACK NAK SYN DLE NUL s mantique e monter le curseur de 2 lignes descendre le curseur de 4 lignes d caler le curseur de 3 positions vers la droite e d caler le curseur de 1 position vers la gauche e

Les 10 premi res commandes ont t cr es pour construire des trames de commue ee e nication entre machines reli es par des lignes synchrones. Elles sont compl tement e e obsol tes de nos jours, o les communications se font gr^ce des r seaux dont les e u a a e trames n'utilisent pas ces caract res. e La derni re commande null tait utile l' poque des t l imprimeurs dont le temps e e a e ee de retour du chariot tait plus grand que le temps d'impression d'un caract re quele e conque. Apr s avoir envoy un carriage return, il fallait envoyer plusieurs null en e e fonction de la vitesse de la ligne pour ^tre s^r que le chariot tait bien revenu en e u e d but de ligne ! e 173

commandes de p riph rique e e commande device control 1 device control 2 device control 3 device control 4 nom DC1 DC2 DC3 DC4

Ces caract res ont t pr vus pour donner des ordres sp ci ques certains p riph e ee e e a e e riques. A l' poque des t l imprimeurs, ceux-ci poss daient un lecteur-perforateur de e ee e ruban papier. Les codes device control taient utilis s pour commander ce lecteure e perforateur. De nos jours device control 3 et device control 1 sont utilis s sous les noms respectifs e de xon et xoff pour r aliser du contr^le de ux. Les caract res device control e o e 3 et device control 1 sont a ect s aux touches Control-q et Control-s du clavier. e Lorsqu'un pilote de terminal cran-clavier g re le contr^le de ux, l'utilisateur peut e e o taper Control-s pour faire stopper une sortie trop rapide pour se donner le temps de la lire sur l' cran, et la faire continuer en tapant Control-q. e commandes diverses commande cancel substitute delete bell nom CAN SUB DEL BEL

Il y a deux caract res qui sont utilis s couramment pour r aliser la fonction d'e acee e e ment du caract re erron  pr c dent : back space et delete. En fonction du caract re e e ee e qui est le plus facile taper sur son clavier, l'utilisateur d sirera choisir l'un ou a e l'autre. Le caract re back space peut sur tout clavier s'obtenir par Control-h, alors e qu'il n'y a pas de Control-quelque-chose correspondant au caract re delete. Selon les e claviers, il peut y avoir une touche marqu e back space, et ou une touche marqu e e e delete, ou une touche marqu e  qui g n re back space ou delete, et qui peut, ou ne e ee peut pas, ^tre con gur e par le set-up du terminal pour g n rer au choix back space e e ee ou delete ! Un utilisateur unix utilise la commande stty pour indiquer au syst me d'exploitae tion le caract re qu'il d sire pour r aliser la fonction d'e acement de caract re. e e e e

174

A.2.1 Les codes ascii en octal
code 000 010 020 030 040 050 060 070 100 110 120 130 140 150 160 170
nul bs dle can sp 
0 8 @ H P X ` h p x

0

soh ht dc1 em
!  1 9 A I Q Y a i q y

1

stx lf dc2 sub
" * 2 : B J R Z b j r z

2

etx eot enq ack bel vt np cr so si dc3 dc4 nak syn etb esc fs gs rs us 
+ 3 ; C K S c k s D L T d l t | $ , 4  5 = E M U e m u F N V ^ f n v ~ & . 6 7 ? G O W _ g o w '

3

4

5

6

7

del

A.2.2 Les codes ascii en hexad cimal e
code 0 1 2 3 4 5 6 7 8 9 A B C D E F 0x00 nul soh stx etx eot enq ack bel bs ht lf vt np cr so si 0x10 dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us 0x20 sp ! "  $  & '   * + , - . 0x30 0 1 2 3 4 5 6 7 8 9 : ; = ? 0x40 @ A B C D E F G H I J K L M N O 0x50 P Q R S T U V W X Y Z ^ _ 0x60 ` a b c d e f g h i j k l m n o 0x70 p q r s t u v w x y z | ~ del 175

A.2.3 Les codes ascii en d cimal e
code 0 10 20 30 40 50 60 70 80 90 100 110 120 0 1 2 3 4 5 6 7 8 9

nul lf dc4 rs 
2 F P Z d n x

soh vt nak us 
3 = G Q e o y

stx etx eot enq ack bel bs ht np cr so si dle dc1 dc2 dc3 syn etb can em sub esc fs gs sp ! "  $  & '
* 4 H R f p z + 5 ? I S g q , 6 @ J T ^ h r | 7 A K U _ i s . 8 B L V ` j t ~ 9 C M W a k u 0 : D N X b l v 1 ; E O Y c m w

del

176

A.3 Les codes ISO-Latin-1
octal 0000 0010 0020 0030 0040 0050 0060 0070 0100 0110 0120 0130 0140 0150 0160 0170 0200 0210 0220 0230 0240 0250 0260 0270 0300 0310 0320 0330 0340 0350 0360 0370 0
NUL BS DLE CAN SP

1
SOH HT DC1 EM

2
STX LF DC2 SUB

3
ETX VT DC3 ESC

4
EOT NP DC4 FS

5
ENQ CR NAQ GS

6
ACK SO SYN RS

7
BEL SI ETB US

( 0 8 @ H P X ‘ h p x

! ) 1 9 A I Q Y a i q y

" * 2 : B J R Z b j r z

# + 3 ; C K S [ c k s {

$ , 4 < D L T \ d l t |

% − 5 = E M U ] e m u }

& . 6 > F N V ^ f n v ~

’ / 7 ? G O W _ g o w
DEL

ı ¨ ¨ ° ¸ À È Ð Ø à è ð ø

` ¡ © ± ¹ Á É Ñ Ù á é ñ ù

´ ˆ ˚ ¸ ¢ £ ª « ² ³ º » Â Ã Ê Ë Ò Ó Ú Û â ã ê ë ò 177 ó ú û

˜ ¤ ¬ ´ ¼ Ä Ì Ô Ü ä ì ô ü

¯ ˝ ¥ µ ½ Å Í Õ Ý å í õ ý

˘ ˛ ¦ ® ¶ ¾ Æ Î Ö Þ æ î ö þ

˙ ˇ § ¯ · ¿ Ç Ï × ß ç ï ÷ ÿ

178

Annexe B

Bibliographie
Il existe de tr s nombeux livres sur le langage C. Il su t de se rendre dans une fnac e quelconque pour en trouver des rayons entiers. Je ne donnerai ici que les livres qui sont extraordinaires pour une raison ou une autre. 1 Brian W. Kernighan and Dennis M. Ritchie. The C programming language. Prentice Hall, seconde dition, 1988. e
Le livre sur C crit par les concepteurs du langage. La seconde dition est conforme au e e standard ansi, alors que la premi re dition m^me titre, m^mes auteurs d nissait le e e e e e langage C dans sa version dite Kernighan et Ritchie".

2 Samuel P. Harbison et Guy L. Steele. C a reference manual. Prentice hall, quatri me e dition, 1995. e

Il y a un consensus sur Internet pour estimer que ce livre est la meilleure r f rence sur le ee langage C. C'est le livre dont un programmeur doit disposer d s qu'il a d pass le stade e e e d'apprentissage du langage.

3 Herbert Schildt. The annotated ANSI C standard. Osborne McGraw-Hill, 1993

L'id e de H. Schildt tait excellente : donner le texte complet de la norme accompagn de e e e commentaires permettant de l' clairer. Malheureusement, le r sultat est consid r comme e e ee tant tr s mauvais par pratiquement tout le monde sur Internet : les annotations de l'auteur e e sont consid r es comme tant sans int ret. Il y a cependant une raison de se procurer ce ee e e livre : obtenir au prix d'un livre le texte o ciel d'une norme qui coute tr s cher si on se la e procure directement aupr s des organismes normalisateurs. e Pour les personnes qui doivent disposer du texte o ciel de la norme avec les derniers amendements. On peut se procurer ce texte aupr s de l'afnor. Consulter http: www.afnor.fr. e Ce livre n'est ni un livre pour apprendre le langage, ni un manuel de r f rence pour programee meur con rm . C'est un m lange d'anecdotes, d' tudes fouill es de certains points di ciles e e e e du langage, de d s de programmation, de r cit de bugs d sastreux etc. Se lit davantage e e e comme un roman que comme un livre technique.

4 International Standard ISO IEC 9899:1990 Programming languages C

5 Peter Van der Linden Expert C programming. Sun Soft Press - A Prentice Hall Title

179

180

Annexe C

Ressources Internet
Les ressources Internet se composent essentiellement de : deux forums de discussion: comp.lang.c : forum international donc en langue anglaise de discussion sur le langage C. fr.comp.lang.c : forum franais de discussion sur le langage C. c deux faq Frequently Asked Questions : La faq de comp.lang.c maintenue par Steve Summit dont l'url est ftp: rtfm.mit.edu: pub usenet news.answers C-faq faq. C'est le recueil des questions les plus fr quemment pos es dans le forum comp.lang.c. e e Un document intitul Learn C C++ today a list of resources tutorials dont e l'url est
ftp:

On y trouve les url de ressources librement accessibles sur Internet, savoir : a des documents imprimer, des documents consulter avec un browser web, a a des exemples de programmes, une bibliographie comment e. e

rtfm.mit.edu: pub usenet news.answers C-faq learn-c-cpp-today.

181

182

Annexe D

La grammaire
D.1 Les unit s lexicales e
R1
unit -lexicale : e  mot-cl e  identi cateur  constante  cha^ne-litt rale
e  op rateur e  ponctuation unit -lexicale-du-pp : e  nom- chier-inclusion  identi cateur  nombre-du-pp  constante-caract re e  cha^ne-litt rale
e  op rateur e  ponctuation  tout caract re non blanc qui ne peut ^tre une des entit s pr c dentes e e e ee

R2

D.2 Les mots-cl s e
R3
mot-cl : un parmi e
auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while

183

D.3 Les identi cateurs
R4
identi cateur :  non-chi re  identi cateur non-chi re  identi cateur chi re non-chi re : un parmi
_ a n A N b o B O c p C P d q D Q e r E R f s F S g t G T h u H U i v I V j w J W k x K X l y L Y m z M Z

R5

R6

chi re : un parmi
0 1

2

3

4

5

6

7

8

9

D.4 Les constantes
R7
constante :  constante- ottante  constante-enti re e  constante-d- num ration e e  constante-caract re e constante- ottante :  partie-fractionnaire partie-exposant option su xe- ottant option  s quence-de-chi res partie-exposant su xe- ottant option e partie-fractionnaire :  s quence-de-chi res option e  s quence-de-chi res . e
.

R8 R9 R10 R11 R12 R13

s quence-de-chi res e

partie-exposant :  e signe option s quence-de-chi res e  E signe option s quence-de-chi res e signe : un parmi
+ -

s quence-de-chi res : e  chi re  s quence-de-chi res chi re e su xe- ottant : un parmi
f l F L

184

R14

constante-enti re : e  constante-d cimale su xe-entier option e  constante-octale su xe-entier option  constante-hexad cimale su xe-entier option e constante-d cimale : e  chi re-non-nul  constante-d cimale chi re e constante-octale :

R15 R16 R17 

0  constante-octale chi re-octal

constante-hexad cimale : e  0x chi re-hexad cimal e  0X chi re-hexad cimal e  constante-hexad cimale chi re-hexad cimal e e chi re-non-nul : un parmi
1 2 3 4 5 6 7 8 9

R18 R19 R20 R21 R22 R23 R24 R25 R26

chi re-octal : un parmi
0 1 2

3

4

5

6

7

chi re-hexad cimal : un parmi e
0 a 1 b 2 c 3 d 4 e

5 f

6 A

7 B

8 C

9 D

E

F

su xe-entier :  su xe-non-sign su xe-long option e  su xe-long su xe-non-sign option e su xe-non-sign : un parmi e
u U

su xe-long : un parmi
l L

constante-d- num ration : e e  identi cateur constante-caract re : e  ' s quence-de-caract res-c e e  L' s quence-de-caract res-c e e s quence-de-caract res-c : e e  caract re-c e
' '

185 

s quence-de-caract res-c caract re-c e e e
R27
caract re-c : e  n'importe quel membre du jeu de caract res source sauf le quote ' e le backslash   ou le newline  s quence-d- chappement e e s quence-d- chappement : e e  s quence-d- chappement-simple e e  s quence-d- chappement-octale e e  s quence-d- chappement-hexad cimale e e e s quence-d- chappement-simple : un parmi e e
' a " b ? f n r t v

R28

R29 R30

s quence-d- chappement-octale : e e  chi re-octal  chi re-octal chi re-octal  chi re-octal chi re-octal chi re-octal s quence-d- chappement-hexad cimale : e e e  x chi re-hexad cimal e  s quence-d- chappement-hexad cimale chi re-hexad cimal e e e e

R31

D.5 Les cha^nes litt rales
e
R32 R33 R34
cha^ne-litt rale :
e  " s quence-de-caract res-s option e e  L" s quence-de-caract res-s option e e
" "

s quence-de-caract res-s : e e  caract re-s e  s quence-de-caract res-s caract re-s e e e caract re-s : e  n'importe quel membre du jeu de caract res source sauf le double quote " e le backslash   ou le newline  s quence-d- chappement e e

D.6 Les op rateurs e
R35
op rateur : un parmi e 
 . -

186

++ ? = ,

-- &  : *= =  

*

+

-

~ =

!

sizeof = == != = = &=

^

|

&& |=

|| 

=

+=

-=

^=

D.7 La ponctuation
R36
ponctuation : un parmi 
 * , : = ; ... 

D.8 Nom de chier d'inclusion
R37 R38 R39 R40 R41
nom- chier-inclusion :  s quence-de-caract res-h e e  " s quence-de-caract res-q e e
"

s quence-de-caract res-h : e e  caract re-h e  s quence-de-caract res-h caract re-h e e e caract re-h : e  n'importe quel membre du jeu de caract res source sauf ou le newline e s quence-de-caract res-q : e e  caract re-q e  s quence-de-caract res-q caract re-q e e e caract re-q : e  n'importe quel membre du jeu de caract res source sauf " ou le newline e

D.9 Les nombres du pr processeur e
R42
nombre-du-pp :  chi re  . chi re  nombre-du-pp chi re  nombre-du-pp non-chi re  nombre-du-pp e signe  nombre-du-pp E signe  nombre-du-pp .

187

D.10 Les expressions
R43
expression-primaire :  identi cateur  constante  cha^ne-litt rale
e   expression 

R44

expression-post x e : e  expression-primaire  expression-post x e e  expression-post x e e  expression-post x e e  expression-post x e e  expression-post x e e  expression-post x e e 

. ++ --

expression liste-d-expressions-param tres option e identi cateur identi cateur 

R45 R46

liste-d-expressions-param tres : e  expression-a ectation  liste-d-expressions-param tres e

,

expression-a ectation

expression-unaire :  expression-post x e e  ++ expression-unaire  -- expression-unaire  op rateur-unaire expression-cast e  sizeof expression-unaire  sizeof  nom-de-type  op rateur-unaire : un parmi e
& * + ~ !

R47 R48 R49

expression-cast :  expression-unaire   nom-de-type 

expression-cast expression-cast expression-cast expression-cast

expression-multiplicative :  expression-cast  expression-multiplicative  expression-multiplicative  expression-multiplicative

* 

R50

expression-additive :  expression-multiplicative  expression-additive + expression-multiplicative  expression-additive - expression-multiplicative

188

R51

expression-d calage : e  expression-additive  expression-d calage e  expression-d calage e expression-relation :  expression-d calage e  expression-relation  expression-relation  expression-relation  expression-relation

expression-additive expression-additive expression-d calage e expression-d calage e expression-d calage e expression-d calage e

R52

= =

R53

expression- galit : e e  expression-relation  expression- galit == expression-relation e e  expression- galit != expression-relation e e expression-et :  expression- galit e e  expression-et & expression- galit e e expression-ou-exclusif :  expression-et  expression-ou-exclusif expression-ou-inclusif :  expression-ou-exclusif  expression-ou-inclusif expression-et-logique :  expression-ou-inclusif  expression-et-logique expression-ou-logique :  expression-et-logique  expression-ou-logique expression-conditionnelle :  expression-ou-logique  expression-ou-logique expression-et expression-ou-exclusif expression-ou-inclusif expression-et-logique expression-conditionnelle

R54 R55 R56 R57 R58 R59 R60 R61

^

|

&&

||

?

expression

:

expression-a ectation :  expression-conditionnelle  expression-unaire op rateur-a ectation expression-a ectation e op rateur-a ectation : un parmi e
= *= = = += -= = = &= ^= |=

189

R62 R63

expression :  expression-a ectation  expression , expression-a ectation expression-constante :  expression-conditionnelle

D.11 Les d clarations e
R64 R65
d claration : e  sp ci cateurs-de-d claration liste-de-d clarateurs-init option e e e
;

sp ci cateurs-de-d claration : e e  sp ci cateur-de-classe-m moire sp ci cateurs-de-d claration option e e e e  sp ci cateur-de-type sp ci cateurs-de-d claration option e e e  quali catif-de-type sp ci cateurs-de-d claration option e e liste-de-d clarateurs-init : e  d clarateur-init e  liste-de-d clarateurs-init e d clarateur-init : e  d clarateur e  d clarateur e d clarateur-init e

R66 R67 R68

,

=

initialisateur

sp ci cateur-de-classe-m moire : e e 

   

auto extern static register typedef

R69

sp ci cateur-de-type : e 

void  char  short  int  long  float  double  signed  unsigned  sp ci cateur-de-struct-ou-union e  sp ci cateur-d- num ration e e e
190 

nom-de-typedef
R70 R71 R72 R73 R74 R75 R76 R77 R78 R79 R80 R81
sp ci cateur-de-struct-ou-union : e  struct-ou-union identi cateur option  struct-ou-union identi cateur struct-ou-union : liste-de-d clarations-de-struct e 



struct union

liste-de-d clarations-de-struct : e  d claration-de-struct e  liste-de-d clarations-de-struct d claration-de-struct e e d claration-de-struct : e  liste-de-sp ci cateurs-et-quali catifs liste-de-d clarateurs-de-struct e e liste-de-sp ci cateurs-et-quali catifs : e  sp ci cateur-de-type liste-de-sp ci cateurs-et-quali catifs option e e  quali catif-de-type liste-de-sp ci cateurs-et-quali catifs option e liste-de-d clarateurs-de-struct : e  d clarateur-de-struct e  liste-de-d clarateurs-de-struct e d clarateur-de-struct : e  d clarateur e  d clarateur option e d clarateur-de-struct e
;

,

:

expression-constante liste-d- num rateurs e e

sp ci cateur-d- num ration : e e e  enum identi cateur option  enum identi cateur liste-d- num rateurs : e e  num rateur e e  liste-d- num rateurs e e

,

num rateur e e expression-constante

num rateur : e e  constante-d- num ration e e  constante-d- num ration e e quali catif-de-type :

= 



const volatile

d clarateur : e  pointeur option d clarateur-direct e

191

R82

d clarateur-direct : e  identi cateur   d clarateur  e  d clarateur-direct e  d clarateur-direct e  d clarateur-direct e pointeur : 



expression-constante option liste-de-types-de-param tres e liste-d-identi cateurs option 



R83 R84 R85 R86 R87 R88 R89 R90 R91 



* *

liste-de-quali catifs-de-types option liste-de-quali catifs-de-types option pointeur

liste-de-quali catifs-de-types :  quali catif-de-type  liste-de-quali catifs-de-types quali catif-de-type liste-de-types-de-param tres : e  liste-de-param tres e  liste-de-param tres e

,

...

liste-de-param tres : e  d claration-de-param tre e e  liste-de-param tres , d claration-de-param tre e e e d claration-de-param tre : e e  sp ci cateurs-de-d claration d clarateur e e e  sp ci cateurs-de-d claration d clarateur-abstrait option e e e liste-d-identi cateurs :  identi cateur  liste-d-identi cateurs identi cateur

,

nom-de-type :  liste-de-sp ci cateurs-et-quali catifs d clarateur-abstrait option e e d clarateur-abstrait : e  pointeur  pointeur option d clarateur-abstrait-direct e d clarateur-abstrait-direct : e   d clarateur-abstrait  e  d clarateur-abstrait-direct option e  d clarateur-abstrait-direct option e nom-de-typedef :  identi cateur expression-constante option liste-de-types-de-param tres option e  

R92

192

R93

initialisateur :  expression-a ectation  liste-d-initialisateurs  liste-d-initialisateurs liste-d-initialisateurs :  initialisateur  liste-d-initialisateurs

,

R94

,

initialisateur

D.12 Les instructions
R95
instruction :  instruction- tiquett e e e  instruction-compos e e  instruction-expression  instruction-s lection e  instruction-it ration e  instruction-saut instruction- tiquett e : e e  identi cateur : instruction  case expression-constante : instruction  default : instruction instruction-compos e : e  liste-de-d clarations option liste-d-instructions option e liste-de-d clarations : e  d claration e  liste-de-d clarations d claration e e liste-d-instructions :  instruction  liste-d-instructions instruction instruction-expression :  expression option
;

R96

R97 R98 R99 R100 R101

instruction-s lection : e  if  expression  instruction  if  expression  instruction else instruction  switch  expression  instruction instruction-it ration : e

R102 

while 

expression 

instruction

193 


R103

do instruction while  for  expression option ;

instruction

expression  ; expression option ; expression option 

instruction-saut : 

  

goto identi cateur ; continue ; break ; return expression option ;

D.13 D nitions externes e
R104 R105 R106
unit -de-compilation : e  d claration-externe e  unit -de-compilation d claration-externe e e d claration-externe : e  d nition-de-fonction e  d claration e d nition-de-fonction : e  sp ci cateurs-de-d claration option d clarateur liste-de-d clarations option e e e e instruction-compos e e

D.14 Directives du pr processeur e
R107 R108 R109
chier-du-pp :  groupe option groupe : 

partie-de-groupe  groupe partie-de-groupe

partie-de-groupe :  liste-d-unit s-lexicales-du-pp option newline e  section-if  ligne-directive section-if : groupe-if :

R110 R111 

groupe-if liste-de-groupes-elif option groupe-else option ligne-endif 
 if expression-constante newline groupe option ifdef identi cateur newline groupe option 



194 

R112 R113 R114 R115 R116 

ifndef

identi cateur newline groupe option

liste-de-groupes-elif :  groupe-elif  liste-de-groupes-elif groupe-elif groupe-elif :  

elif

expression-constante newline groupe option newline groupe option newline

groupe-else :  

else

ligne-endif :  

endif

ligne-directive : 

  

   
R117 R118 R119 R120

liste-d-unit s-lexicales-du-pp newline e identi cateur remplacement newline identi cateur parenth se-g liste-d-identi cateurs option e remplacement newline  undef identi cateur newline  line liste-d-unit s-lexicales-du-pp newline e  error liste-d-unit s-lexicales-du-pp option newline e  pragma liste-d-unit s-lexicales-du-pp option newline e  newline 
  include define define

parenth se-g : e  le caract re  non pr c d d'un espace blanc e eee remplacement :  liste-d-unit s-lexicales-du-pp option e liste-d-unit s-lexicales-du-pp : e  unit -lexicale-du-pp e  liste-d-unit s-lexicales-du-pp unit -lexicale-du-pp e e newline : 

le caract re s parateur de lignes e e

195

D.15 R f rences crois es de la grammaire ee e
caract re-c e caract re-h e caract re-q e caract re-s e cha^ne-litt rale
e chi re chi re-hexad cimal e chi re-non-nul chi re-octal constante constante-caract re e constante-d- num ration e e constante-d cimale e constante-enti re e constante- ottante constante-hexad cimale e constante-octale d clarateur e d clarateur-abstrait e d clarateur-abstrait-direct e d clarateur-de-struct e d clarateur-direct e d clarateur-init e d claration e d claration-de-param tre e e d claration-de-struct e d claration-externe e d nition-de-fonction e num rateur e e expression expression-additive expression-a ectation expression-cast expression-conditionnelle expression-constante expression-d calage e expression- galit e e expression-et expression-et-logique expression-multiplicative expression-ou-exclusif expression-ou-inclusif expression-ou-logique expression-post x e e expression-primaire

27 26 39 38 41 40 34 33 2 1, 2, 43 6 4, 42 20 17, 31 18 15 19 16, 30 7 1, 43 25 2, 7 24 7, 79 15 14, 15 14 7 87 17 14, 17 16 14 81 67, 76, 82 87, 106 90 87, 89, 91 91 90, 91 76 75 82 81, 82 67 66 64 98, 105 87 86 73 72 105 104 106 105 79 78 62 43, 44, 59, 62, 100, 101, 102, 103 50 50, 51 60 45, 60, 62, 93 48 46, 48, 49 59 59, 60, 63 63 76, 79, 82, 91, 96, 111, 113 51 51, 52 53 53, 54 54 54, 55 57 57, 58 49 49, 50 55 55, 56 56 56, 57 58 58, 59 44 44, 46 43 44
196

expression-relation expression-unaire chier-du-pp groupe groupe-elif groupe-else groupe-if identi cateur initialisateur instruction instruction-compos e e instruction- tiquett e e e instruction-expression instruction-it ration e instruction-saut instruction-s lection e ligne-directive ligne-endif liste-d- num rateurs e e liste-de-d clarateurs-de-struct e liste-de-d clarateurs-init e liste-de-d clarations e liste-de-d clarations-de-struct e liste-de-groupes-elif liste-de-param tres e liste-de-quali catifs-de-types liste-de-sp ci cateurs-et-quali catifs e liste-de-types-de-param tres e liste-d-expressions-param tres e liste-d-identi cateurs liste-d-initialisateurs liste-d-instructions liste-d-unit s-lexicales-du-pp e mot-cl e newline nom-de-type nom-de-typedef nom- chier-inclusion nombre-du-pp non-chi re op rateur e op rateur-a ectation e op rateur-unaire e parenth se-g e partie-de-groupe partie-exposant partie-fractionnaire

52 52, 53 46 46, 48, 60 107 108 107, 108, 111, 113, 114 113 112 114 110 111 110 4 1, 2, 4, 24, 43, 44, 70, 77, 82 88, 92, 96, 103, 111, 116 93 67, 94 95 96, 99, 101, 102 97 95, 106 96 95 100 95 102 95 103 95 101 95 116 109 115 110 78 77, 78 75 73, 75 66 64, 66 98 97, 98, 106 72 70, 72 112 110, 112 86 85, 86 84 83, 84 74 73, 74, 89 85 82, 91 45 44, 45 88 82, 88, 116 94 93, 94 99 97, 99 119 109, 116, 118, 119 31 120 27, 109, 111, 113, 114, 115, 116 89 46, 48 92 69 37 2 42 2, 42 5 4, 15, 42 5 1, 2 61 60 47 46 117 116 109 108 10 8 98
197

pointeur ponctuation quali catif-de-type remplacement section-if s quence-de-caract res-c e e s quence-de-caract res-h e e s quence-de-caract res-q e e s quence-de-caract res-s e e s quence-d- chappement e e s quence-d- chappement-hexad cimale e e e s quence-d- chappement-octale e e s quence-d- chappement-simple e e s quence-de-chi res e signe sp ci cateur-d- num ration e e e sp ci cateur-de-classe-m moire e e sp ci cateur-de-struct-ou-union e sp ci cateur-de-type e sp ci cateurs-de-d claration e e struct-ou-union su xe-entier su xe- ottant su xe-long su xe-non-sign e unit -de-compilation e unit -lexicale e unit -lexicale-du-pp e

83 81, 83, 90 36 1, 2 80 65, 74, 84 118 116 110 109 26 25, 26 38 37, 38 40 37, 40 33 32, 33 28 27, 34 31 28, 31 30 28 29 28 12 8, 9, 10 11 10, 42 77 69 68 65 70 69 69 65, 74 65 64, 65, 87, 106 71 70 21 14 13 8 23 21 22 21 104 104 1 2 119

198

Annexe E

Un bestiaire de types
E.1 Les types de base
formes quivalentes e
short short int signed short signed short int int signed signed int long long int signed long signed long int unsigned short unsigned short int unsigned unsigned int unsigned long unsigned long int char signed char unsigned char float double long double

forme pr f r e eee
short int

s mantique e entier court entier entier long entier court non sign e entier non sign e entier long non sign e caract re e caract re sign e e caract re non sign e e ottant simple pr cision e ottant double pr cision e ottant quadruple pr cision e

int

long int

unsigned short int unsigned int unsigned long int

199

E.2 Les tableaux
int tab 10 ; int tab 5 = 10, 11, 12, 13, 14 ; char mes 80 ; char mess = "Erreur de syntaxe"; int t 24 80 ; int t1 2 3 = 0, 1, 2 , 10, 11, 12 ; int *t 10 ; int i, j, k; int *t 3 = &i, &j, &k ; char *t = "lundi", "mardi", "mercredi", ; struct complex float x,y; ; struct complex t 10 ; struct complex float x,y; ; struct complex t 3 = 1.5, 2.4 , 1, 3.2 , 0.7, 3 ; struct complex float x,y; ; struct complex * t 10 ; struct complex float x,y; ; struct complex r1, r2, r3; struct complex *t = &r1, &r2, &r3 ; int *t 10 int; int f1int a * corps de la fonction *

tableau de 10 entiers tableau de 5 entiers avec initialisation tableau de 80 caract res e tableau de caract res avec initialisation e tableau deux dimensions a tableau deux dimensions avec initialisation a tableau de pointeurs vers des entiers tableau de pointeurs vers des entiers avec initialisation tableau de pointeurs vers des caract res e avec initialisation tableau de structures tableau de structures avec initialisation tableau de pointeurs vers des structures tableau de pointeurs vers des structures avec initialisation tableau de pointeurs vers des fonctions

int f2int a * corps de la fonction *

tableau de pointeurs vers des fonctions avec initialisation

int *t 2 int =

f1, f2 ;

200

E.3 Les pointeurs
int *p; int i; int *p = &i; int **p; int *q; int **p = &q; struct complex float x,y; struct complex *p; struct complex float x,y; struct complex c; struct complex *p = &c; int *pint; int *pint,float; void *pint; int fint a * corps de la fonction *

; ;

pointeur vers un entier pointeur vers un entier avec initialisation pointeur vers un pointeur vers un entier pointeur vers un pointeur vers un entier avec initialisation pointeur vers une structure pointeur vers une structure avec initialisation pointeur vers une fonction ayant un param tre entier et retournant un entier e pointeur vers une fonction ayant un param tre entier et un param tre ottant et e e retournant un entier pointeur vers une fonction ayant un param tre entier et ne retournant pas de valeur e pointeur vers une fonction ayant un param tre entier et retournant un entier, avec e initialisation

int *pint = f;

E.4 Les fonctions
void fvoid * corps de la fonction *

fonction sans param tre et sans valeur ree tourn e e fonction avec un param tre entier, sans vae leur retourn e e fonction sans param tre retournant un int e fonction avec un param tre entier et un e param tre ottant, retournant un int e fonction avec un param tre entier et un e nombre variable de param tres, retoure nant un int 201

void fint a * corps de la fonction *

int fvoid * corps de la fonction *

int fint a, float b * corps de la fonction *

int fint a, ... * corps de la fonction *

E.5 Les num rations e e
enum coul bleu, blanc, rouge ; enum coul bleu, blanc=10, rouge ; enum coul bleu=3, blanc=5, rouge=9 ; bleu bleu bleu

= 0, blanc = 1 et rouge = 2 = 0, blanc = 10 et rouge = 11 = 3, blanc = 5 et rouge = 9

E.6 Les structures, unions et champs de bits
struct complex float x; * partie r elle e float y; * partie imaginaire ; struct complex float x; * partie r elle e float y; * partie imaginaire c1, c2; struct float x; * partie r elle e float y; * partie imaginaire c; enum type ENTIER, FLOTTANT struct arith enum type typ_val; union int i; float f; u; ; struct sr unsigned unsigned unsigned unsigned unsigned unsigned unsigned unsigned unsigned unsigned ; * *

Structure deux champs ottants. D a e nit l' tiquette de structure complex sans e d clarer de variable. e Structure deux champs ottants. D nit a e l' tiquette de structure complex et d clare e e les deux variables c1 et c2. Structure deux champs ottants. D a e clare la variable c sans d nir d' tiquette e e pour la structure. Union d'un type entier et d'un type ottant associ dans une structure a un indie cateur le champ typ_val permettant de connaitre le type de la valeur stock e dans e l'union u.

* *

* *

int int int int int int int int int int

trace : 2; priv : 2; : 1; masque : 3; : 3; extend : 1; negative : 1; z ro : 1; e overflow : 1; carry : 1;

Champs de bits : description du registre d' tat du mc68000. Il s'agit d'un mot de e 16 bits. Les troisi me et cinqui me champs e e ne portent pas de nom.

202

E.7 Les quali catifs
Il y a deux quali catifs : const et volatile Les exemples pr sent s sont avec const, e e l'utilisation de volatile tant rigoureusement identique. e
const const int * const int i; int *p; const p; int * const p;

const int t 5 ; struct coord int x; int y; ; const struct coord s;

Entier constant Pointeur vers un entier constant. Pointeur constant vers un entier. Pointeur constant vers un entier constant. Tableau constant : tous les l ments de t ee sont constants. Structure constante : tous les champs de s sont constants.

203

204

Annexe F

Le b^tisier e
Cette annexe est une collection des b^tises qu'il faut faire au moins une fois dans sa vie e pour ^tre vaccin . La caract ristique de beaucoup de ces erreurs est de ne pas provoquer e e e de message d'erreur du compilateur, rendant ainsi leur d tection di cile. La di rence e e entre le texte correct et le texte erron est souvent seulement d'un seul caract re. La e e d couverte de telles erreurs ne peut donc se faire que par un examen tr s attentif du e e source du programe.

F.1 Erreur avec les op rateurs e
F.1.1 Erreur sur une comparaison
Ce que voulait le programmeur Ce qu'il aurait d^ crire ue Ce qu'il a crit e Ce qu'il a obtenu Comparer a et b
if a == b if a = b

une a ectation de b a, suivie d'une a comparaison 0 de la valeur a eca t e. e

Comment est ce possible?
L'a ectation est un op rateur et non pas une instruction. e

F.1.2 Erreur sur l'a ectation

C'est le pendant de l'erreur pr c dente. ee Ce que voulait le programmeur Ce qu'il aurait du crire e Ce qu'il a crit e Ce qu'il a obtenu A ecter b a a
a = b; a == b;

La comparaison de a b, suivie de a l'inutilisation du r sultat. e

Comment est ce possible?
Une d rivation possible pour instruction est : e instruction : 205 

expression option

;

Pour que cela ait un sens, il faut que l'expression r alise un e et de bord, mais rien ne e l'impose dans la d nition du langage. e

F.2 Erreurs avec les macros
Le m canisme des macros est r alis par le pr processeur qui r alise un traitement en e e e e e amont du compilateur proprement dit. Le traitement des macros est un pur traitement textuel, sans aucun contexte ; c'est un nid a erreurs.

F.2.1 Un define n'est pas une d claration e
Ce que le programmeur a crit e 
define MAX 10;

Ce qu'il aurait du crire e 
define MAX 10

Cette erreur peut provoquer ou non une erreur de compilation l'utilisation de la a macro : L'utilisation x = MAX; aura pour expansion x instruction nulle derri re x = 10;. e L'utilisation int t message d'erreur.
MAX ; = 10;;,

ce qui est licite : il y a une ce qui g n rera un ee

aura pour expansion

int t 10; ;

F.2.2 Un define n'est pas une initialisation
Ce que le programmeur a crit e 
define MAX = 10

Ce qu'il aurait du crire e 
define MAX 10

Cette erreur sera g n ralement d tect e la compilation, malheureusement le message ee e e a d'erreur sera mis sur l'utilisation de la macro, et non pas l o r side l'erreur, a savoir la e a u e d nition de la macro. e

F.2.3 Erreur sur macro avec param tres e
La distinction entre macro avec param tres et macro sans param tre se fait sur la e e pr sence d'une parenth se ouvrante juste apr s le nom de la macro, sans aucun blanc e e e entre les deux. Ceci peut amener des r sultats surprenant ; comparer les deux exemples e suivants : D nition de la macro e 
define adda,b a + b define add a,b a + b

param tres corps de la macro e a et b a + b aucun a,b a + b 206

F.2.4 Erreur avec les e ets de bord
Le corps d'une macro peut comporter plusieurs occurrences d'un param tre. Si a l'utie lisation de la macro on r alise un e et de bord sur le param tre e ectif, cet e et de bord e e sera r alis plusieurs fois. Exemple : e e 
define CARREa a * a

l'utilisation de CARREx++ aura comme expansion sera appliqu deux fois. e 

x++ * x++

et l'op rateur e

++

F.3 Erreurs avec l'instruction if
L'instruction if ne comporte ni mot-cl introducteur de la partie then, ni terminateur e pas de fi dans le style des if then else . Ceci peut provoquer les erreurs suivantes : Ce que le programmeur a crit e
if  a b ; a = b;

Ce qu'il aurait du crire e
if  a b a = b;

Le probl me vient aussi du fait de l'existence de l'instruction nulle. e Ce que le programmeur a crit e
if a b if  x else ... y x = y;

Ce qu'il aurait du crire e
if a b if  x else ... y x = y;

On rappelle qu'un else est raccroch au premier if. e

F.4 Erreurs avec les commentaires
Il y a deux erreurs classiques avec les commentaires : 1. le programmeur oublie la s quence fermante *. Le compilateur mange" donc tout e le texte jusqu' la s quence fermante du prochain commentaire. a e 2. On veut enlever en le mettant en commentaire un gros bloc d'instructions sans prendre garde au fait qu'il comporte des commentaires. Les commentaires ne pouvant ^tre imbriqu s, a n'aura pas l'e et escompt par le programmeur. La m thode e e c e e classique pour enlever tout en le laissant dans le source un ensemble d'instructions est d'utiliser le pr processeur : e 
ifdef NOTDEFINED ... endif

207

F.5 Erreurs avec les priorit s des op rateurs e e
Les priorit s des op rateurs sont parfois surprenantes. Les cas les plus g^nants sont les e e e suivants : La priorit des op rateurs bit bit est inf rieure a celle des op rateurs de comparaie e a e e son. Le programmeur a crit il d sirait e e il a obtenu
x & 0xff == 0xac x & 0xff == 0xac x & 0xff == 0xac

La priorit des op rateurs de d calage est inf rieure a celle des op rateurs arithm e e e e e e tiques. Le programmeur a crit il d sirait e e
x 4 + 0xf x 4 + 0xf

il a obtenu
x 

4 + 0xf

La priorit de l'op rateur d'a ectation est inf rieure a celle des op rateurs de come e e e paraison. Dans la s quence ci-dessous, tr s souvent utilis e, toutes les parenth ses e e e e sont n cessaire : e
while c = getchar != EOF ...

F.6 Erreur avec l'instruction switch
F.6.1 Oubli du break
L'instruction de s lection a pour syntaxe : instruction-s lection : e e  switch  expression  instruction La notion d'alternative de la s lection n'appara^t pas dans la syntaxe : le programmeur e
doit les r aliser par une liste d'instruction tiquett e par case expression-constante et e e e termin e par break. En cas d'oubli du break, une catastrophe s'ensuit. e

F.6.2 Erreur sur le default

L'alternative a ex cuter par d faut est introduite par l' tiquette default. Si une faute e e e de frappe est commise sur cette tiquette, l'alternative par d faut ne sera plus reconnue : e e l' tiquette sera prise pour une tiquette d'instruction sur laquelle ne sera fait aucun goto. e e
switcha case 1 : a = b; defult : return1;

*

erreur non d tect e e e

*

Une version diabolique de cette erreur est relat e dans le livre de Peter Van Der e Linden : si la lettre l de default est remplac e par le chi re 1, avec les fontes utilis es e e pour imprimer les sources, qui verra la di rence entre l et 1 ? e 208

F.7 Erreur sur les tableaux multidimensionnels
La r f rence un tableau t deux dimensions s' crit t i j et non pas t i,j ee a a e comme dans d'autres langages de programmation. Malheureusement, si on utilise par erreur la notation t i,j selon le contexte d'utilisation, elle pourra ^tre accept e par le e e compilateur. En e et, dans cette expression la virgule est l'op rateur qui d livre comme e e r sultat l'op rande droit apr s avoir valu l'op rande gauche. Comme l' valuation de e e e e e e e l'op rande gauche ne r alise ici aucun e et de bord, cette valuation est inutile , donc e e e t i,j est quivalent t j qui est l'adresse du sous-tableau correspondant l'index j. e a a

F.8 Erreur avec la compilation s par e e e
Une erreur classique est d'avoir un tableau d ni dans une unit de compilation : e e
int tab 10 ;

et d'utiliser comme d claration de r f rence dans une autre unit de compilation : e ee e
extern int * tab;

Rappelons que int tab et int *t ne sont quivalents que dans le seul cas de param tre e e formel de fonction. Dans le cas qui nous occupe ici, la d claration de r f rence correcte e ee est :
extern int tab ;

209

210

Glossaire
Pour chaque mot de ce glossaire on indique par la notation G n ral si il s'agit d'un e e concept g n ral dans le domaine des langages de programmation, par Mat riel si il s'agit ee e d'un concept du domaine de l'architecture des machines, et par Jargon C si il s'agit d'un particularisme du langage C. Derri re cette indication, nous donnons le mot anglais utilis e e pour d signer ce concept. e

adresse Mat riel ; Anglais : address. La m moire d'une machine est form e d'une suite e e e
d' l ments m moires. L'adresse d'un l ment est son rang dans la suite. Voir aussi : ee e ee l ment m moire. ee e leur dans la case m moire correspondant une variable. L'a ectation est g n ralee a ee ment r alis e par une instruction, dans le langage C, elle est r alis e par un op rateur. e e e e e d clarations et des instructions. e
vrai et faux.

a ectation G n ral ; Anglais : assignment. Op ration qui a pour but de stocker une vae e e bloc G n ral ; Anglais : block. Construction d'un langage qui permet de regrouper des e e bool en G n ral ; Anglais : boolean. type dont l'ensemble des valeurs est form des valeurs e e e e cha^ne de caract res G n ral ; Anglais : string. Suite contigue en m moire de carac
e e e e
t res. e

champ G n ral ; Anglais : eld. Un l ment d'un enregistrement. e e ee champ de bits Jargon C ; Anglais : bit eld. Un champ de structure C dont la taille est
donn e en nombre de bits. e

compilation s par e G n ral ; Anglais : separate compilation. Technique qui consiste a e e ee compl ment 2 Mat riel ; Anglais : 2's complement. Le compl ment 2 est une m e a e e a e

d couper les gros programmes en di rentes unit s de compilation pour en ma^triser e e e
la complexit . Les di rentes unit s sont compil es s par ment, et un diteur de liens e e e e e e e est charg de transformer les modules objets en programme ex cutable. e e thode de repr sentation des nombres sign s. Les nombres positifs sont repr sent s e e e e en base 2. Sur 8 bits, la repr sentation de la valeur 6 est 00000110 et celle de 10 e est 00001010. Pour les nombres n gatifs, on part de la valeur absolue que l'on ree pr sente en binaire, on la compl mente bit bit et on additionne 1. Sur 8 bits, la e e a repr sentation de -6 est 11111010 et celle de -10 est 11110110 e 211

une entit du langage. Il y a des d clarations de variable, de type, de proc dure, de e e e fonction. L'identi cateur est un nom pour l'entit d clar e. e e e dur e de vie G n ral ; Anglais : lifetime. Concept qui s'applique aux variables. La dur e e e e e de vie d'une variable est le temps qui s' coule entre le moment o on alloue de la e u m moire pour cette variable, et le moment o on r cup re la m moire allou e. Il e u e e e e existe classiquement trois types de dur e de vie : e - dur e de vie du programme : la variable est cr e au chargement du programme e ee et d truite a la n du programme. Une telle variable est dite statique. e - dur e de vie d'un bloc : la variable est cr e quand on entre dans le bloc et e ee d truite quand on en sort. Une telle variable est quali e de dynamique. e e - dur e de vie programm e : la variable est cr e et d truite par des ordres explie e ee e cites du programmeur. Une telle variable est quali e de dynamique. e Voir aussi : pile, tas, statique, dynamique. e et de bord G n ral ; Anglais : side e ect. Modi cation de l' tat de la machine. Un e et e e e de bord peut ^tre interne au programme par exemple, modi cation de la valeur e d'une variable ou externe au programme par exemple criture dans un chier. e Toute partie de programme qui n'est pas d clarative a pour but soit de calculer une e valeur, soit de faire un e et de bord. Voir aussi : proc dure, fonction. e l ment m moire Mat riel ; Anglais : storage unit. Une fraction de la m moire accessible ee e e e en une seule instruction machine. Une machine comporte g n ralement au moins ee trois types d' l ments m moire : un l ment permettant de stocker un caract re, et ee e ee e un l ment permettant de stocker un entier, et un l ment permettant de stocker un ee ee ottant. enregistrement G n ral ; Anglais : record. Type d ni par l'utilisateur permettant de e e e regrouper en une seule entit , des variables de types di rents. Au sein de l'enregise e trement, les variables sont identi es par un nom. e ensemble G n ral ; Anglais : set. Le concept math matique d'ensemble. Certains lane e e gages l'o rent Pascal, Modula-2, d'autres pas Algol, C, Ada. valuation G n ral ; Anglais : evaluation. Ce concept s'applique une expression. Evae e e a luer une expression c'est calculer sa valeur. Voir aussi : valuation court-circuit. e valuation court circuit G n ral ; Anglais : short circuit evaluation. Se dit d'une vae e e e luation qui n' value pas tous les op randes. Par exemple, dans le langage C, l'op e e e rateur && value d'abord son op rande gauche, si celui-ci est faux, il n'y aura pas e e d' valuation de l'op rande droit. e e fonction G n ral ; Anglais : function. Poss de en commun avec la proc dure d'associer e e e e un nom a un traitement algorithmique, mais la caract ristique d'une fonction est de e d livrer une valeur utilisable dans une expression. Les langages de programmation e permettent g n ralement aux fonctions, en plus du fait de retourner une valeur, de ee faire un ou plusieurs e ets de bord. Voir aussi : proc dure. e 212

d claration G n ral ; Anglais : declaration. Construction qui associe un identi cateur et e e e

langage de programmation, on parle d'identi cateur pour dire nom. initialisation G n ral ; Anglais : initialization. op ration consistant donner une valeur e e e a initiale a une variable. Il y a deux types d'initialisation: les initialisations statiques  la d claration de la variable et les initialisations dynamiques r alis es par des a e e e instructions. membre Jargon C ; Anglais : member Le mot utilis en C pour dire champ d'un enree gistrement. mot-cl G n ral ; Anglais : keyword. Un mot dont la signi cation est x e par le langage, e ee e par opposition aux identi cateurs qui sont librement choisis par le programmeur. objet G n ral ; Anglais : object. Voir source. e e param tre e ectif G n ral ; Anglais : e ective parameter ou argument. La valeur qui est e e e pass e en param tre a la fonction. e e param tre formel G n ral ; Anglais : formal parameter ou parameter. Le nom d'un pae e e ram tre dans la d claration d'une proc dure ou fonction. e e e passage de param tre G n ral ; Anglais : parameter passing. Technique de communie e e cation de param tre entre l'appelant et une proc dure ou fonction appel e. Il existe e e e diverses faons de passer les param tres dont les plus utilis es sont le passage par c e e valeur et le passage par adresse. Le langage C n'utilise que le passage par valeur. pile G n ral ; Anglais : stack. Dans un langage r cursif, les variables locales une proe e e a c dure doivent ^tre allou es dans une pile, car un moment donn il peut y avoir e e e a e plusieurs activations en cours de la m^me proc dure, et donc plusieurs instanciations e e des variables de la proc dure. Voir aussi : dur e de vie, tas. e e pointeur G n ral ; Anglais : pointer. Type dont les valeurs possibles sont des adresses de e e variable. port e G n ral ; Anglais : scope. Ce concept s'applique aux identi cateurs. La port e e ee e d'un identi cateur est la partie du programme o l'ensemble des occurences d'un u identi cateur font r f rence a la m^me d claration. Ce sont les blocs qui permettent ee e e de limiter la port e d'un identi cateur. e proc dure G n ral ; Anglais : procedure. Permet d'associer un nom un traitement ale e e a gorithmique. La proc dure est la brique de base de la construction de programme. e Le but d'une proc dure est de r aliser au moins un e et de bord sinon elle ne sert e e a rien. r cursivit G n ral ; Anglais : recursivity. Propri t d'une proc dure ou fonction a s'ape e ee ee e peler elle-m^me. Les langages les plus anciens Fortran, Cobol ne sont pas r cursifs, e e les langages modernes Pascal, C sont r cursifs. e source G n ral ; Anglais : source. Forme du programme crit en langage de programe e e mation. Par opposition objet qui est la forme du programme une fois traduit en a instructions machines. Entre la source et l'objet, la s mantique est conserv e, seule e e la forme change. 213

identi cateur G n ral ; Anglais : identi er. Synonyme de nom. Dans le domaine des e e

s mantique d pend du contexte. Dans le langage C, le surchargement des op rateurs e e e est une v ritable plaie : * est a la fois op rateur d'indirection et de multiplication, & e e est la fois op rateur adresse de " et and bit a bit", etc ... a e tas G n ral ; Anglais : heap. Zone de la m moire o sont e ectu es les allocations dynae e e u e miques de variables explicitement demand es par le programmeur. Dans le langage e C, les allocations et les lib rations dans le tas se font par des fonctions de la biblioe th que standard : calloc et malloc pour les allocations, free pour les lib rations. e e Voir aussi : dur e de vie, pile. e type G n ral ; Anglais : type. Attribut d'une variable qui d termine l'ensemble des valeurs e e e que peut prendre cette variable et les op rateurs qu'on peut lui appliquer. e type de base G n ral ; Anglais : basic type. type qui est connu du langage, par opposition e e aux types d nis par le programmeur. Classiquement, les types de base sont bool en, e e caract re, entier, ottant. Le langage C n'a pas le type bool en. e e type d ni par le programmeur G n ral ; Anglais : user-de ned type. On n'a pas ine e e vent de nom pour ce concept : il est d sign par une p riphrase. A partir des types e e e e de base, le programeur peut construire de nouveaux types : tableau de type, pointeur vers type, etc ... type entier Jargon C ; Anglais : integral type. Regroupe les types suivants : - les char - toutes les vari t s de int : sign s, non sign s, longs ou courts. ee e e - les types num r s d nis par enum. e ee e type ottant Jargon C ; Anglais : oating type. Regroupe les float, double et long double. unit de compilation G n ral ; Anglais : compilation unit. Un des chiers source come e e posant un programme d velopp selon la technique de la compilation s par e. Voir e e e e aussi : compilation s par e. e e variable G n ral ; Anglais : variable. Une abstraction du concept d' l ment m moire. e e ee e variable globale G n ral ; Anglais : global variable. Variable d clar e l'ext rieur de e e e e a e toute proc dure ou fonction. Les variables globales sont accessibles par toutes les e proc dures et fonctions. e variable locale G n ral ; Anglais : local variable. Variable d clar e l'int rieur d'une e e e e a e proc dure ou fonction. Les variables locales sont inaccessibles l'ext rieur de la e a e proc dure ou fonction dans laquelle elles sont d clar es. e e e

structure Jargon C ; Anglais : structure. Synonyme d'enregistrement. surchargement G n ral ; Anglais : overloading. Un symbole est dit surcharg quand sa e e e

214

Index 
define, 15, 117 elif, 139 else, 139 error, 140 if, 139 ifdef, 140 ifndef, 140 include, 22 DATE , 135 FILE , 135 LINE , 135 STDC , 135 TIME , 135

a ectation, voir op rateur = e de structure, 105 allocation de m moire, 46, 109 e ansi, 5, 81 argc, 77 argv, 77 ascii, 10 associativit e op rateur, 129 e auto, 148, 150 biblioth que standard, 5, 27, 29, 56, 81, e 109 big endian, 115, 128 bloc, 20 bool en, 154, 211 e break, voir instruction, break
calloc,

109 caract re e ;, 20 escape , 12 newline , 12 null , 12, 14, 36, 49 return , 12 case, 57 215

cast, voir op rateur, conversion e cdecl, 163 cha^ne de caract res, 14, 27, 37, 76, 77, 79
e cha^ne litt rale, 14, 36, 69, 76, 78
e champs de bits, 114 char, 10 classe de m moire, 149 e commande du pr processeur, 15, 21, 26, 139 e commentaire, 7 common, 151 compilateur, 6 mise en oeuvre du, 29, 134, 140 version, 5 compilation conditionnelle, 139 compl ment a 2, 10, 120 e const, 69, 155 constante, 14 caract re, 11 e cha^ne de caract res, voir cha^ne lit
e
t rale e d cimale, 11 e enti re, 11 e ottante, 13 hexad cimale, 11 e nomm e, 14 e octale, 11 continue, voir instruction, continue conversion, 17 arithm tiques habituelles, 122 e de cha^ne litt rale, 69
e de tableau, 65, 109 de types, 119 cpp, 6 d claration, 20, 28, 143 e d'union, 116, 144 de fonction, 22, 26, 153 de pointeur, 45

de structure, 103, 144 de tableau, 35, 72 de variable, 16, 22 port e de, 145 e default, 57 defined, 140 d nition, 143 e d' tiquette d' num ration, 115 e e e d' tiquette d'union, 116 e d' tiquette de branchement, 59 e d' tiquette de structure, 103 e de constante, 14 de fonction, 22 d pendance de l'impl mentation, 10, 18, e e 22, 115 do, voir instruction, do double, 10, 89, 96, 122 dur e de vie, 148 e diteur de liens, 7, 29, 150, 151 e e et de bord, 16, 19, 25, 38, 40, 41, 95 else, 20 entier, voir type, entier entr e standard, 56 e entr es-sorties, 27 e enum, 15, 115 num ration, 15, 115 e e EOF, 84, 85, 88, 95 EOF, 56 espace de noms, 146 tiquette, 59 e d'union, 116, 144 de structure, 103, 144 valuation des op randes, 17 e e exit, 29 exposant, 13 extern, 26, 128, 144, 150, 152 fclose, 83 fgetc, 84 fgets, 86 chier d'inclusion, 22 FILE, 82, 88 float, 10, 89, 96, 122 ottant, voir type, ottant fonction appel de, 24 d nition, 22 e 216

externe, 26 prototype de , voir prototype, de fonction r cursive, 25, 144 e fopen, 81 for, voir instruction, for fprintf, 89 fputc, 85 fputs, 87 free, 110 fscanf, 94 fseek, 82
getc, 84 getchar, 85 gets, 87 goto, voir instruction, goto

identi cateur, 7, 15, 22, 103 if, voir instruction, if imbrication de blocs, 146 de commentaires, 7 de fonctions, 25 initialisation de structure, 105 de tableau, 36, 73 de variables simples, 16 instruction break, 39, 57 compos e, 20 e continue, 40 do, 39, 138 expression, 19, 41 for, 37, 60 goto, 59 if, 20 nulle, 59 return, 22, 25, 29 switch, 57 while, 38 int, 10, 19 iso, 5
k&r, 5, 26, 46

lib ration de m moire, 109 e e linux, 136

little endian, 115, 128 long, 10, 11, 89, 96, 122 lvalue, 16, 37, 40, 41

macro, 133 avec param tres, 135 e corps de, 135 expansion de, 133, 135 pr d nie, 135 ee sans param tre, 133 e main, 28, 29 malloc, 46, 109 mantisse, 13 membre de structure, 103 acc s aux, 107, 117 e mot-cl , 7 e nombre entier, 10 ottant, 10 NULL, 81, 82, 86, 121 op rateur e !, 43 !=, 19
*

adresse de, 46, 52, 56 et bit a bit, 125 &&, 42 ^, 125 ~tilde, 124 |, 125 ||, 42 adresse de , voir op rateur & e a ectation, voir op rateur = e a ectation compos e, 127 e conversion, 127 d'adressage, 129 de comparaison, 19 d cr mentation, voir op rateur -e e e et logique, voir op rateur && e incr mentation, voir op rateur ++ e e indexation, 37, 66 indirection, voir op rateur * e modulo, voir op rateur  e ou logique, voir op rateur || e sizeof, 109, 123, 128 sur les structures, 105, 107 ordre d' valuation, 131 e param tre e de programme, 77 e ectif, 24 formel, 22 nombre variable de, 156 passage de, 52 par adresse, 52 par valeur, 52 passage de structure en, voir structure, passage en param tre e passage de tableau en, voir tableau, passage en param tre e pointeur arithm tique sur, 49 e concept de, 45 conversion d'un, 120 conversion vers, 121 et op rateurs ++ et --, 49 e et op rateurs + et -, 49 e et tableau, 65 g n rique, 45, 128 ee invalide, voir NULL 217

indirection, 46 multiplication, 18 +, 17 ++, 40 ,virgule, 126 -, 17 --, 41 - , 107 .point, 105 , 18 , 19 , 125 =, 19 =, 16, 19 ==, 19 , 19 =, 19 , 125 ?:, 126 , 18
&

vers une structure, 107 pr processeur, 6, 15, 81, 117 e printf, 27, 70, 92 priorit e op rateur, 129 e proc dure, voir fonction e programme, 28 promotion des entiers, 121 prototype de fonction, 22 ptrdiff t, 50 putc, 86 putchar, 86 puts, 88 quali catif de type, 155 r cursivit e e de fonction, voir fonction, r cursive e de structure, voir structure, r cursive e register, 149, 150 return, voir instruction, return
scanf,

surcharge d'op rateur, 119 e de *, 46 de break, 59 switch, voir instruction, switch tableau de caract res, 36, 37 e de pointeurs, 75 de structure, 105 d claration, 35 e l ment de, 37, 72 ee et pointeur, 65 g n ralit , 65 ee e initialisation, voir initialisation de tableau multidimensionnel, 72 passage en param tre, 67, 68, 72 e taille de, 35 trigraphe, 11 type, 153 caract re, 10 e entier, 10, 96, 120 ottant, 10, 96, 120 quali catif de, 155 typedef, 150, 153 union, 116, 144 unit de compilation, 7, 28, 151 e unit lexicale, 6 e unsigned, 10, 11, 89, 96, 114, 122, 123, 125
va va va va arg, 156 end, 156 list, 156 start, 156

56, 99 s quence d' chappement, 11, 14, 27, 56, e e 89, 96 shell, 29, 79, 131, 134 short, 10, 89, 96, 122 signed, 115 sizeof , voir operateur, sizeof sprintf, 93 sscanf, 99 static, 148, 150 stderr, 83 stdin, 83 stdout, 83 struct, 103, 144 structure, 144 a ectation, voir a ectation, de structure d claration, voir d claration, de struce e ture initialisation, voir initialisation, de structure op rateurs sur, voir op rateurs, sur e e les structures passage en param tre, 108 e r cursive, 107 e 218

variable globale, 28 locale, 22, 28, 53 version, 5 visibilit , 146 e void, 22 25, 45, 89, 121, 128 volatile, 155
while,

voir instruction, while

Sign up to vote on this title
UsefulNot useful