Académique Documents
Professionnel Documents
Culture Documents
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
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
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 bibliothque 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 caractres . . . . . . . . . . . . . . . . .
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 paramtres . . . . . . . . . . . . . . . . . . . . . . . . . . . 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 dernire pr cision . . . . . . . . . . . . . . . . . . . . . . . . . . . e e 3.13 Exercice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.14 Lecture formatt e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e 3.15 Les dernires 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
Conversion des tableaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . L'op
rateur d'indexation . . . . . . . . . . . . . . . . . . . . . . . . . . . . e Passage de tableau en paramtre . . . . . . . . . . . . . . . . . . . . . . . e Modi cation des
l
ments d'un tableau pass
en paramtre . . . . . . . . ee e e Interdiction de modi cation des
l
ments d'un tableau pass
en paramtre 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 Accs aux
l
ments . . . . . . . . . . . . . . . . . . . . . . . . . . . e ee 4.9.3 Passage en paramtre . . . . . . . . . . . . . . . . . . . . . . . . . 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 Paramtres 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.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 caractre sur chier e e 5.3.1 lecture par caractre : fgetc . . . . . e v
81
81 81 81 83 84 84
5.4
5.5
5.3.2 lecture par caractre : getc . . . . . . . . . . . e 5.3.3 lecture par caractre : getchar . . . . . . . . . e 5.3.4
criture par caractre : fputc . . . . . . . . . . e e 5.3.5
criture par caractre : putc . . . . . . . . . . . e e 5.3.6
criture par caractre : 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.1 Notion de structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2 D claration de structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . e 6.3 Op rateurs sur les structures . . . . . . . . . . . . . . . . . . . . . . . . . e 6.3.1 Accs 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 Accs aux l ments d'une structure point e . . . . . . . . . . . . . . . . . e ee e 6.9 Passage de structures en paramtre . . . . . . . . . . . . . . . . . . . . . . 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 Accs aux membres de l'union . . . . . . . . . . . . . . . . . . . . . . . . . e vi
103
6.17 Utilisation pratique des unions . . . . . . . . . . . . . . . . . . . . . . . . . 116 6.18 Une m thode pour all ger l'accs 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 paramtres . . . e 8.1.2 Macros pr d nies . . . . . . . . ee 8.1.3 Les macros avec paramtres . . . e 8.1.4 Les piges 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 problme . . . . . . . . . . . . . . . . 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 problme . . . . . . . . . . . . . . . . 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 paramtres . . . . . . . . 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 caractres 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 paramtres stdarg.h . . . . . e Entr es sorties stdio.h . . . . . . . . . . . . . . . e 10.8.1 Op rations sur les chiers . . . . . . . . . . . e 10.8.2 Accs 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
165
10.8.4 Entr
es-sorties caractres . . . . . . . . . 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 caractres 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.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
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 paramtres . . . 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
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'aprs avoir programm
sa solution e e personnelle, ou bien lire directement la solution comme si elle faisait partie du manuel.
traduction d'un grand diteur 1 de livres techniques, m^me quand je n'ai pas trouv ces e e e choix trs 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 rgles 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 rgles 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 rgles de grammaires seront
crites de la manire suivante : e e e les parties gauches de rgles 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 manires possibles de d
river le non-terminal inse e truction. La premire rgle indique qu'on peut le d
river en : e e e if expression instruction 1 la deuxime rgle indique qu'on peut aussi le d
river en : e e e if expression instruction 1 else instruction 2 une partie droite de rgle pourra ^tre
crite sur plusieurs lignes. Ceci permettra e e e de r
ter une manire 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 :
les
l
ments optionnels d'une rgle 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 rgle : e
d
clarateur-init : e d
clarateur initialisateur option 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 particulirement Damien e e Genthial, Fabienne Lagnier, Xavier Nicollin et Serge Rouveyrol.
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
algorithmique d clarations, instructions, etc. et tout ce qui est interaction avec le syse tme 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 bibliothque dite bibliothque standard. Cette coupure se retrouve e e dans la norme qui est compos e essentiellement de deux grands chapitres, les chapitres e langage et bibliothque . e Ce manuel se donne comme objectif de donner une vue d'ensemble du langage, mais pas de la bibliothque standard. De la bibliothque standard ne seront pr sent es de manire e e e e e complte 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 bibliothque, class s par type e e d'utilisation, est donn e dans le chapitre 10. 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 entire. 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 caractre 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 caractres. e e e e De la m^me manire, 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
vre, mais ne peut ^tre inf
rieure a 6 caractres. 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.
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 paramtres 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 espces 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
*
* * * * * * * *
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
Attention
Le type caractre 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 caractre 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 caractre e e suivant dans le code utilis
sur la machine. e
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
Caractres 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 caractre s mantique e e ' "' ou '"' " ' ?' ou '?' ? S mantique : e Une constante caractre est de type int et a pour valeur le code du caractre dans e e le codage utilis par la machine. e 12
Note
Pourquoi diable les deux caractres " et ? disposent ils de deux notations possibles? e Le caractre " peut ^tre repr
sent
par la notation ' "' parce que celle-ci doit e e e e ^tre utilis
e dans les cha^nes de caractres 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 caractres ne soit pas valable pour un caractre.
e e Le caractre ? est un cas part cause de l'existence des trigraphes. Les trie a a graphes sont des s
quences de trois caractres permettant de d
signer les caractres e e e e ^ | ~. En e et, les terminaux conformes la norme iso 646:1983 ont a remplac
ces caractres par des caractres nationaux. Les franais, par exemple, e e e c connaissent bien le problme 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
??= ?? ?? ?? ??' ?? ?? ??! ??
| ~
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
: : : : :
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 caractre 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 :
Si deux cha^nes litt
rales sont adjacentes dans le source, le compilateur concatne 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 caractre mis a z
ro. Le caractre
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 bibliothque standard. Exemple : sur rencontre
e e de "Hello!" le compilateur implantera en m
moire 7 caractres H, e, l, l, o, !, 0. e e Dans une cha^ne de caractres litt
rale, le caractre " 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
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.
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.
On peut d
nir des constantes de la manire 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 particulires aux constantes, e e cela est possible :
enum FRANCE = 10, 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 entirement 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
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;
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 entire un ottant. e a
1.12.2 L'addition
Syntaxe : expression :
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. Aprs valuation des expressions, il peut y avoir conversion de type de l'un des e e op randes, de manire 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 manire unaire ou binaire : e e e e
expression :
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 entire e e e e a e et la division entre ottants. Si expression 1 et expression 2 d livrent deux valeurs entires, alors il s'agit d'une e e division entire. 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 entire, 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.
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 entire 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 entire 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.
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
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'aprs 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
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
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
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.
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
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
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 manire dont se fait la recherche du chier inclure est d pendante de l'impl mene a e e tation. Dans le systme unix, il est traditionnel de se conformer la rgle suivante : e a e si on utilise et , le chier est un chier systme, il sera recherch dans un ou plue e sieurs r pertoires systmes 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
Dans le jargon C, l'ensemble : type identi cateur liste-de-d
clarations-de-paramtres 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-paramtres est la liste s
par
s par des virgules e e e e des d
clarations des paramtres 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 paramtres formels sont les int i et j e d
claration des variables locales 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 paramtres formels sont les int i et j e pas de variables locales pour max * * *
if i
Si la dernire 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
Attention
La syntaxe des d
clarations pour les paramtres 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 paramtres formels. Il n'est pas possible e e d'
crire max de la manire suivante : e e
int maxint i,j ... * incorrect *
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 ramtres 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 paramtre, la liste-d'expressions doit ^tre vide : il e e n'est pas possible d'utiliser le mot cl
void en tant que paramtre e ectif. e e
d = pivoid; * appel incorrect de pi *
2. L'ordre d'
valuation des paramtres 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;
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 paramtres formels e e une variable locale print_add a * *
* *
* *
* *
* *
Problme 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.
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 manire r cursive. Voici un exemple de factorielle : e e e
25
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 bibliothque standard. Avant d'utiliser une fonction de la bibliothque 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 manire 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
Dans la documentation concernant les fonctions de la bibliothque 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
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.
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-paramtres a e e est remplac
par une liste d'identi cateurs, qui sont les noms des paramtres. La d
clarae e e tion des types des paramtres se fait juste aprs, de la manire suivante : e e e
int sum_squarei,j int i, int j; int resultat; resultat = i*i + j*j; returnresultat; * * liste des noms des paramtres formels e d
claration du type des paramtres 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 paramtres, comme e e e e ceci :
extern int sum_square;
Dans ce cas, le compilateur ne conna^t pas le type des paramtres de la fonction, il lui
e est donc impossible de d
tecter une erreur portant sur le type des paramtres 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.
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-caractres ;
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 *
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
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 systme 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 paramtre 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 paramtres 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
* * * * * * * * * * * *
28
* * *
d but du main, il n'a pas de paramtre e e instructions qui appellerons p1 et f1 fin de la d finition de main e
* * *
essai1.
Pour v
ri er qu'il n'y a pas de problme 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 entires heures, minutes, secondes ; e e
7. Sous unix ce sera le shell de l'utilisateur
1.20 Exercice
29
en respectant l'orthographe du singulier et du pluriel; 3. une proc dure set_heure qui admettra trois paramtres 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-aprs. 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 problme avec le langage C : le compilateur utilis
en 1990 par B. Westley e e n'
tait pas ansi et acceptait le su xe s derrire une constante entire 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 paramtre 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=
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 trs utiles pour mettre en uvre ces instructions. e e
* *
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 ;
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 ;
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.
Un tableau de caractres peut ^tre initialis
par une liste de constantes caractres. e e e e Exemple :
char ch 3 = 'a', 'b', 'c' ;
C'est
videmment une m
thode trs lourde. e e e Un tableau de caractres peut ^tre initialis
par une cha^ne litt
rale. Exemple : e e e
e
char ch 8 = "exemple";
On se rappelle que le compilateur complte toute cha^ne litt
rale avec un caractre e
e e null, il faut donc que le tableau ait au moins un
l
ment de plus que le nombre de ee caractres 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 caractres 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 caractres 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 caractres"; e
36
Il est
galement possible de donner au tableau une taille
gale au nombre de carace e tres 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 :
S
mantique : expression 1 doit d
livrer une valeur entire, 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 * *
for
expression 2 option
expression 3 option
expression1
? ? ? ?
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.
while
expression
instruction
? ?
non n du while
2.2.3 Instruction do
Syntaxe : instruction :
do
instruction
while
expression
;
2.2.4 Instruction break
Syntaxe : instruction :
instruction
? ?
expression != 0? oui
non n du do
break ;
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 :
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 * *
Le langage C o re un op rateur d'incr mentation qui peut ^tre utilis soit de manire e e e e e pr x , soit de manire 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
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;
* *
* *
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
* *
* *
Une boucle for de parcours de tableau s' crit typiquement de la manire suivante : e e
41
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
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;
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;
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 ;
44
Chapitre 3
Les pointeurs
3.1 Notion de pointeur
Une valeur de type pointeur repre 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
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 bibliothque standard est d nie de la manire 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 manire 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 manire e e suivante :
char *mallocsize;
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 lve 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.
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 aprs: d n",i; e
48
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 reprent les
l
ments d'un m^me tableau a e e ee e ou l'
l
ment ctif aprs 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 aprs le dernier
l
ment d'un tableau a
t
introduite pour ee ee e ee ee les problmes 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 caractre ' 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 repre l' l ment courant de mess e e e *
49
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 ; * * repre le premier l ment de t e e e repre 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; * repre le premier l ment de t e e e * * repre 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";
51
valeur du paramtre e ectif correspondant. Il faut donc programmer add de la manire e e suivante :
void addint a, int b, int *c * c repre 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 paramtres e * on passe l'adresse de k comme troisime paramtre 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 deuxime 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 paramtre par adresse est entirement g
r
e e ee par le programmeur. C'est la charge du programmeur de d
clarer le paramtre 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 paramtre e ectif. a e
53
On voit que le paramtre 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 trs 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 caractres 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 caractres mess initialis
avec le message en clair ; e e e 2.
crire une proc
dure crypt de cryptage d'un caractre 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 caractre pass en paramtre e e e * * * * Interface: * * p : pointe le caractre 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' *p = *p -26;
***************************************************************************** * * * main * * * ***************************************************************************** int main char *p; int i; * phase de cryptage p = &mess 0 ; while*p cryptp++; *
55
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 paramtres 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.
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 paramtres 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 problme. 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 trs di cile a e la d tection de l'erreur. e
56
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
: :
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 premire 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 premire 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. Premire possibilit , on peut avoir dans chaque alternative une e e liste-d'instructions et un break; comme dans l'exemple suivant :
Discussion
57
enum
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
Deuxime 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 caractres, e e le nombre de caractres qui sont des chi res, et le nombre de caractres 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++;
Troisime 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 problme de lisibilit
, car l'exp
rience montre e e e que l'absence du break; est trs 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 manire compltement di
rente. e e e
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 aprs d finition de l' tiquette e e e
* * * * *
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 manire 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 aprs 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 manire 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
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.
Rgle : 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;
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 premire concerne l'op rateur d'indexation et la seconde le passage de e e tableaux en paramtre. e
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
,p
tant t e
, etc. p peut
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 paramtre 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 paramtre formel de la manire suivante : e e e
void procint t ... * * corps de la proc
dure proc e
car le langage assure que lorsqu'un paramtre 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
, int nb_elem
d finition de imp_tab e
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 manire suivante : e
define NB_ELEM 10 int tab NB_ELEM ; int main imp_tabtab,NB_ELEM;
Remarque
Quand une fonction admet un paramtre de type tableau, il y a deux cas possibles: e soit les di
rents tableaux qui lui sont pass
s en paramtre e ectif ont des tailles e e e di
rentes, et dans ce cas la taille doit ^tre un paramtre 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 paramtre 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 paramtre 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 mtre e
Lorsqu'on passe un paramtre 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 paramtre. 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 paramtre se fasse par adresse et non e par valeur et qu'il s'agisse d'une exception la rgle qui a rme qu'en C, tout passage a e de paramtre 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
nomne. 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 paramtre. 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 paramtre 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 paramtre 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 manire 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 paramtres 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 *
ou ^tre utilis
es dans une expression et ^tre pass
es en paramtre de fonction par exemple, e e e e e comme cela :
printf"Bonjour";
69
Rgle e
Lorsque les cha^nes litt
rales apparaissent dans un autre contexte qu'une d
claration
e e avec initialisation de tableau de caractres, elles subissent une conversion en pointeur vers e char. Si une fonction a comme paramtre formel un tableau de caractres, on pourra lui e e passer en paramtre e ectif aussi bien le nom d'un tableau de caractres 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";
* *
* *
4.8 Exercice
1. D
clarer et initialiser deux tableaux de caractres ch1 et ch2. e e
2. Ecrire une fonction lg_chaine1 qui admette en paramtre un tableau de caractres e e se terminant par un null, et qui rende le nombre de caractres 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 paramtre 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 caractres";
e char ch2 = "et celle ci fait 30 caractres"; e ***************************************************************************** * * * lg_chaine1 * * * * But: * * calcule la longueur d'une cha^ne de caractres
e * * * * Interface: * * ch : la cha^ne de caractres
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.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 manire 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 premire ligne, avec ee e a e le type pointeur vers tableau de 20 int.
Lorsqu'on d sire qu'un paramtre 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 premire 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 premire dimension pourra ^tre pass
e e e e en paramtre, 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 premire 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 paramtre 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
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++
74
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-aprs trois m thodes di rentes d'imprimer les l ments du tableau ligne par ligne. e e e ee
Premire 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
Deuxime 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++ * accs l'
l
ment courant par p j e a e e
La dernire 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++
Troisime m thode e e
for j = 0; j taille i ; j++ printf"d ", tab i j ; * accs l' l ment courant par tab i e a e e printf" n";
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 compltea e e ment di
rente. Que l'accs deux structures de donn
es di
rentes puissent se r
aliser e e a e e e de la m^me manire, doit sans doute ^tre consid
r
comme une faiblesse du langage. e e e ee C'est pour les tableaux de caractres 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 ;
1. Alors qu'en toute rigueur il faudrait utiliser le type tableau de pointeurs vers des tableaux de char
76
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 ;
Les tableaux de pointeurs vers des cha^nes de caractres sont une structure de donn
es
e e importante, car c'est sur celle-ci que s'appuie la transmission de paramtres lors de l'ex
e e cution d'un programme. Lorsqu'un utilisateur lance l'ex
cution du programme prog avec e les paramtres param1, param2, ... paramn, l'interpr
teur de commandes collecte tous ces e e mots sous forme de cha^nes de caractres, cr
e un tableau de pointeurs vers ces cha^nes,
e e
et lance la proc
dure main en lui passant deux paramtres : e e un entier contenant la taille du tableau ; le tableau de pointeurs vers les cha^nes.
Pour que le programme puisse exploiter les paramtres pass
s par l'utilisateur, la fonce e tion main doit ^tre d
clar
e de la manire suivante : e e e e
int mainint argc, char *argv ...
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 paramtres, nous donnons le source d'un programme e qui imprime son nom et ses paramtres : e
int mainint argc, char *argv int i; printf"Nom du programme : s n", argv 0 ; for i = 1; i argc; i++ printf"Paramtre d : s n",i,argv i ; e
77
4.13.1 Commentaires
Bien noter les points suivants : Le point important a comprendre dans la rgle 2 est que tableau de x est la m^me e e chose que pointeur vers x uniquement dans le cas de paramtre 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 rgle 1 et rgle 2 : une d claration int t 10 qui n'est pas un e e e e paramtre 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 paramtre formel int t , c'est la d claration elle-m^me qui est e e e e transform e en int *t. e
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 caractres qu'il initialise avec les caractres 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 caractres qu'il initialise de la m^me e e manire 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 caractre de la cha^ne. e
78
char t
= "Hello";
t:
\0
char *p = "Hello";
p:
\0
Ceci est un cas particulier des tableaux de caractres 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 possde 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 caractre a e dans la cha^ne " 021six 012 0" et "have" 1 est le caractre 'a'. On peut donc
e r
crire le programme : ee
main printf"six 012 0", 'a' + "fun" -0x60;
5.
"fun" + 1
donc :
printf"six n","un";
main
80
Chapitre 5
Utilisation
fopen nom-de-
chier
mode
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 systmes font la distinction entre chiers binaires et e chiers textes. Cette distinction n'a pas cours dans le systme 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 paramtre 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
Utilisation
fclose
ot-de-donn es 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
ot-de-donn es e
Description
La fonction fgetc lit un caractre 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 caractre 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 *
84
Description
La fonction getchar est rigoureusement
quivalente getcstdin. C'est
galement e a e une macro, mais comme elle n'admet pas de paramtre, elle n'a pas le petit inconv
nient e e de getc.
ot-de-donn es e
Description
La fonction fputc
crit le caractre carac dans le chier ot-de-donn
es. e e e
Valeur rendue
La fonction fputc rend le caractre
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 * *
85
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.
Description
Un appel putcharc est rigoureusement identique fputcc,stdout. a
taille
ot-de-donn es e
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 caractres 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 caractre libre dans le tableau. fgets a e complte alors les caractres lus par un caractre 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 *
Valeur rendue
gets rend NULL dans le
un pointeur vers le tableau de caractres 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
paramtre 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
Utilisation
fputs cha^ne ,
ot-de-donn es e
1. L'attaque d'Internet connue sous le nom de the Internet worm a pro t de la pr sence dans le e e systme 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 caractre e e null. Le tableau de caractres 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;
Utilisation
puts cha^ne
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
Valeur rendue
La fonction fprintf retourne le nombre de caractres
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 caractres ordinaires c'est a dire di
rents du caractre
e e e qui doivent ^tre copi
s tels quels, et des s
quences d'
chappement introduites par le e e e e caractre , d
crivant la manire dont doivent ^tre
crits les paramtres 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 excs sont
valu
s, e e e e mais leur valeur est ignor
e. e
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 caractre 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 manire 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 aprs. 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 manire 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
Un nombre entier d cimal optionnel indiquant la taille minimum du champ e d'impression, exprim e en caractres. Si param i s' crit sur un nombre de carace e e tres 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
le nombre minimum de chi res pour les formats d, i, o, u, x et X. le nombre de chi res aprs 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 caractres 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 caractre *. Si le e e e e caractre * 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 caractre * 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 caractre 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.
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 caractre 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.
91
Dans les cas qui pr
cdent, 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
g,G
param i sera interpr
t
comme un unsigned char. ee param i sera interpr
t
comme l'adresse d'un tableau de caractres ee e termin
ou non par un null. Les caractres du tableau seront ime e prim
s jusqu'au premier des deux
vnements possibles: e ee impression de pr
cision caractres 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 caractres
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 entire et partie frace tionnaire de la mantisse. La partie entire 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 entire 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
cde, l'utilisation ee du format G implique l'utilisation du format E la place du format a e. Un caractre est
crit. e e
Utilisation
La fonction printf admet un nombre variable de paramtres. Son utilisation est la e suivante : printf format , param 1 , param 2 , ... , param n
Description
Un appel printffmt,
Utilisation
La fonction sprintf admet un nombre variable de paramtres. 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 caractres
mis par sprintf ne sont pas
crits dans un chier, mais dans e e e e le tableau de caractres cha^ne. Un null est
crit dans cha^ne en n de traitement. e
e
93
94
format est une cha^ne de caractres 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, aprs 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 caractres 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 caractres lus du chier d
ni par ot-de-donn
es. e e e e caractres blancs il s'agit des six caractres suivants : espace, tab, line feed, new line, e e
vertical tab et form feed.
d
modle un modle est la description d'un ensemble de cha^nes de caractres. Exemple : e e
e
est le modle 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 modle quand elle appartient l'en
a e a
semble des cha^nes d
crites par le modle. Exemple :
e e d. est conforme au modle e
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
modle 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. modle 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. modle 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. modle 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
modle 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
e,f,g
modle pour une suite de caractres 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 caractres 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 modle pour une suite de caractres non blancs. Le parami correspone e dant est interpr
t
comme un pointeur vers un tableau de caractres ee e su samment grand pour contenir la cha^ne lue plus un null terminal.
modle 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 caractre introduit une s
quence particu
e e lire destin
e d
nir un scanset. La s
quence est form
e du caractre e e a e e e e , suivi d'une suite de caractres quelconques, suivi du caractre . Si e e le premier caractre aprs le crochet ouvrant n'est pas le caractre ^, e e e le scanset est l'ensemble des caractres entre crochets. Si le caractre e e aprs le crochet ouvrant est le caractre ^, le scanset est l'ensemble e e des caractres ne se trouvant pas dans la cha^ne entre crochets. Le e
scanset peut comprendre le caractre 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 modle pour une suite de caractres appare e tenant au scanset. Le parami correspondant est interpr
t
comme ee un pointeur vers un tableau de caractres su samment grand pour e contenir la cha^ne lue plus un null terminal.
modle pour un pointeur
crit d'une manire 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 modle. 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 caractres 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 modle pour le caractre . La directive complte 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 excs 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 caractres blancs, consiste consommer dans e e e a le ot d'entr
e la plus longue s
quence possible de caractres 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 caractres ordinaires, consiste consommer e e e a dans le ot d'entr
e une s
quence identique la directive. Au premier caractre e e a e di
rent, la directive a
chou
et ce caractre 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 caractres 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 caractres e e e qui soit conforme au modle. Si cette s
quence est de taille nulle, la directive a e e
chou
. e e 3. si la directive ne contient pas le caractre *, 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
45
par le format "d d" : la premire 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 premire 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
nomne 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 aprs 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".
Utilisation
La fonction scanf admet un nombre variable de paramtres. Son utilisation est la e suivante : scanf format , param 1 , param 2 , ... , param n
Description
Un appel scanffmt,... est rigoureusement identique fscanfstdin,fmt,.... a
Utilisation
La fonction sscanf admet un nombre variable de paramtres. 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 caractres lus par sscanf ne sont pas lus depuis un chier, mais du tableau de e caractres 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 pice, 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 caractres 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
Premire 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 caractres nomm
nom, le second e e un tableau de 20 caractres 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 manire suivante : e e
struct personne p1,p2;
103
personne
de noms p1 et p2;
Deuxime 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
Troisime 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 premire 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
Une structure peut ^tre initialis
e par une liste d'expressions constantes la manire e e a e des initialisations de tableau. Exemple :
"Jean", "Dupond", 7845 ;
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 caractre du nom de e e p2, on crira : p2.nom 0 . e
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 :
Aucune comparaison n'est possible sur les structures, m^me pas les op rateurs == et !=. e 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;
index dans tab_com * * dernier index valide dans tab_com aprs 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
a l'aide de la d claration : e
on d
clarera une variable de type pointeur vers une telle structure de la manire suivante : e e
struct personne *p;
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 dernire structure de la liste devra avoir un membre suivant dont la valeur e sera le pointeur NULL que nous avons vu en 5.1
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;
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
Attention
En langage C k&r, il n'est pas possible de passer en paramtre une structure, mais e on peut passer un pointeur vers une structure. 108
109
,p
, ... p
nb_elem-1
On libre l'espace allou
par malloc ou calloc au moyen de la proc
dure free qui e e e admet un seul paramtre : 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.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 mtre. 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 paramtre un e pointeur vers la struct commande qui est t^te de la liste complte, et rendra un e e pointeur vers la structure recherch
e. e 3. le main sera modi
de manire 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
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
* *
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 manire 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 &.
qui d
clare les identi cateurs LUNDI, MARDI, etc. comme
tant des constantes entires 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 : aprs 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 rgles 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 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
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 entire, soit une valeur ottante, mais pas e e les deux a la fois.
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 manire 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;
Si on passe en paramtre 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 possde un entier ou un c e ottant.
117
118
Chapitre 7
Les expressions
Ce chapitre d
bute par l'
tude des conversions, problme 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
Conversions vers un type entier depuis un type entier La rgle est de pr
server, si c'est possible, la valeur math
e e e
si le type destination est un type sign
, on considre 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 rgle 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 rgles de conversions d'entiers e vers entiers.
depuis un pointeur Un pointeur peut ^tre converti en un type entier. Pour cela il e
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 paramtre : le paramtre e ectif n'a pas le type du paramtre 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 rgles 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 rgle 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
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 rgle 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 manire 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.
La rgle 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 manire 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 rgles 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 manire 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";
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'aprs 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
nre 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
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
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
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
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
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
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
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;
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
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
= 1
lvalue
+=
expression 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;
2. cause de l'absence de prototype de fonction qui rendait impossible la d
claration a e du type des paramtres des fonctions externes. Si une proc
dure p attendait un e e paramtre 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
* . &
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 entire. 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 ++.
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
. ++ 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 ds 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
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 aprs 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
La version C
Aprs 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 obsolte 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 paramtre de write d
signe la sortie standard, et e e ~-~-~-13 vaut 10 le code de newline. Le troisime paramtre 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.
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 paramtre 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
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
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.
est trs 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 systme unix : la compilation du chier fic.c en e d
nissant la macro sans paramtre de nom NB LIGNES et de valeur 24 : e e
cc -c -DNB_LIGNES=24 fic.c
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
Une macro avec paramtres se d nit de la manire suivante : e e e nom liste-de-paramtres-formels reste-de-la-ligne e
La liste-de-paramtres-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-paramtres-e ectifs e Dans la liste-de-paramtres-e ectifs, les paramtres sont s
par
s par des virgules et chaque e e e e paramtre est une suite quelconque d'unit
s lexicales. Le pr
processeur remplace l'ene e e semble nom de la macro et liste de paramtres e ectifs parenth
s
s, par reste-de-la-ligne e ee dans lequel chaque paramtre formel est remplac
par le paramtre 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 paramtres 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 paramtre se fait sur le caractre qui suit e e imm
diatement le nom de la macro : si ce caractre est une parenthse ouvrante c'est une e e e macro avec paramtres, sinon c'est une macro sans paramtre. En particulier, si aprs le e e e nom de la macro il y a un blanc avant la parenthse ouvrante, a sera une macro sans e c paramtre. 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 paramtres a e e et la parenthse 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-aprs : 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
Le second paramtre 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
Par le fait que le traitement des macros consiste faire de la substitution de texte, a l' criture de macros recle de nombreux piges. e e e
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 manire !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 rgles dans la d
nition d'une macro e e devant ^tre utilis
e dans des expressions : e e 1. parenth
ser les occurrences des paramtres formels ; e e 2. parenth
ser le corps complet de la macro. e Une d
nition de CARRE respectant ces rgles est : e e
define CARREa a * a
l'utilisation de CARREx++ aura comme expansion x++ donc appliqu deux fois. e 137
* x++,
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 piges 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;
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 ... ;
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 ...
pour comprendre le problme : 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
La commande permettant de r aliser la compilation conditionnelle est la commande e qui peut prendre plusieurs formes.
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
ensemble-de-lignes else
endif
Un seul ensemble-de-lignes sera compil : celui correspondant la premire 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
Dans ce qui pr cde 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
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
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 systme 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 systme sur lequel il s'ex
cute. Prenons par exemple le systme unix qui existe en deux e e e grandes variantes : la variante bsd et la variante system v. La routine de recherche d'un caractre 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
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 manire plus formelle. e 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 * * * *
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 considre 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 possde la partie instruction : c'est une d
finition e e int minint a, int b returna b ? a : b; *
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 procde de la manire 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
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
146
* *
* *
Dans l'instruction s1.i = s2.i, il y a deux occurrence du nom i, la premire 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
147
Remarque
Certains auteurs considrent
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.
Discussion
148
Dans d'autres langages, de manire 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
ceci est une indication au compilateur, lui permettant d'allouer la variable dans une ressource de la machine dont l'accs sera plus rapide que l'accs une m moire si une telle e e a e ressource existe.
149
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 * * * *
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 paramtres 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 accs 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 trs 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 manire 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.
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
La d claration e
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 adhre 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 adhre 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
d
clare personne comme
tant le type structure a deux champs : un tableau de 20 carace e tres 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 * *
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;
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
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
154
on voit que la seconde m
thode permet d'
viter d'avoir r
p
ter struct. e e a ee De la m^me manire, 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;
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 *
s mantique e caractre constant e pointeur vers caractre constant e pointeur constant vers caractre e pointeur constant vers caractre constant e
permet de d clarer une variable opaque au programmeur, passer en paramtre e a e aux autres macros. Cette variable s'appelle traditionnellement ap pour argument pointer, et a pour but de rep rer le paramtre 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 paramtres : la variable ap et le nom du dernier paramtre obligatoire de la fonction. e e d livre le paramtre e ectif courant : le premier appel a va arg d livre le premier e e e paramtre, puis chaque nouvel appel va arg d livre le paramtre suivant. La macro e a e e va arg admet deux paramtres : la variable ap et le type du paramtre courant. e e doit ^tre appel e aprs toutes les utilisations de va arg. La macro va end admet e e e un seul paramtre : la variable ap. e
va arg
va end
Rien n'est pr vu pour communiquer la fonction le nombre et le type des paramtres e a e e ectivement pass s : c'est un problme 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 paramtres ope e tionnels.
include stdio.h include stdarg.h ***************************************************************************** * * * addn * * * * But: * * r
alise l'addition d'un nombre variable de paramtres 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;
* * * *
* * * *
Dans cet exemple, le problme du nombre de paramtres e ectifs a t r gl par un parae e ee e e mtre obligatoire de la fonction : nbopd. En ce qui concerne le type des paramtres 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 bibliothque standard, il y a deux fonctions utilis
es couramment qui ade e mettent un nombre variable de paramtres : 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 paramtres optionnels. Ce pro
e blme est r
gl
par les s
quences d'
chappement se trouvant dans le paramtre obligatoire : e e e e e e le nombre de paramtres optionnels est
gal au nombre de s
quences d'
chappement ; e e e e le type de chaque paramtre optionnel est cod
dans sa s
quence
chappement : c e e e e pour char, d pour int, etc. 157
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
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
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
;
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
159
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-paramtres : e liste-de-paramtres e liste-de-paramtres e
...
liste-de-paramtres : e d claration-de-paramtre e e liste-de-paramtres , d claration-de-paramtre e e e d claration-de-paramtre : 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
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
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 rgle : e d
clarateur-direct : e d
clarateur e permet de parenth
ser des d
clarateur de manire 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
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 manire homogne, 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 trs 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 manire, 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.
2. A l'utilisation il faudra mettre les paramtres e ectifs e 3. En juillet 96, on peut le trouver sur hpftp.cict.fr: hpux
Misc cdecl-1.0
163
164
Chapitre 10
10.1 Diagnostic
La fonction assert permet de mettre des assertions dans le source du programme. A l'ex
cution, si le paramtre de assert s'
value faux, le programme est stopp
sur e e e a e terminaison anormale.
ctype.h
Toutes les fonctions ci-dessous permettent de tester une propri
t
du caractre pass
ee e e en paramtre. e
isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit
le paramtre est e une lettre ou un chi re une lettre un caractre de commande e un chi re d cimal e un caractre imprimable ou le blanc e une lettre minuscule un caractre imprimable pas le blanc e un caractre imprimable pas isalnum e un caractre d'espace blanc e une lettre majuscule un chi re hexad cimal e
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.
math.h
fonction s
mantique e exp exponentielle frexp
tant donn
, trouve et tels que = 2p e e ldexp multiplie un nombre par une puissance entire de 2 e log logarithme logarithme d
cimal e log10 modf calcule partie entire et d
cimale d'un nombre e e
x n
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
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
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
Si on d sire programmer une fonction avec un nombre variable de paramtres, on e e dispose de trois macros : va_start, va_arg et va_end.
stdio.h
fonction description fermeture de chier criture sur chier des bu ers en m moire e e ouverture de chier ouverture de chier
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 caractres e e
e lecture formatt
e depuis une cha^ne de caractres e
e variante de fprintf variante de printf variante de sprintf 167
fonction description fgetc lecture d'un caractre e fgets lecture d'une cha^ne de caractres
e fputc
criture d'un caractre e e fputs
criture d'une cha^ne de caractres 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 caractres 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 caractres sur la sortie standard e
e refoule un caractre sera lu par la prochain lecture e ungetc
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
fonction
Les fonctions suivantes permettent de convertir des nombres entre la forme cha^ne de
caractres 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
Trois de ces fonctions ont t vues au paragraphe 6.11. La liste exhaustive est calloc, ee et realloc.
Deux fonctions : bsearch et qsort. fonction description abs valeur absolue div obtention de quotient et reste labs idem abs sur des long int
Les caractres multi-octets permettent de prendre en compte les langues qui ne peuvent e se satisfaire de caractres cod s sur 8 bits. La liste exhaustive des fonctions est : mblen, e e mbtowc, wctomb, mbstowcs, wcstombs.
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
time.h
170
Annexe A
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 caractre carriage return est la commande permettant de mettre la poe sition d' criture en d but de ligne, sans changer de ligne. Le caractre 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 caractre carriage return suivi a e d'un caractre line feed ou l'inverse. Dans le systme unix, le caractre choisi par e e e convention comme signi ant passage la ligne est le caractre line feed, et c'est a a e la charge des pilotes de p riph riques de remplacer ce caractre logique par la suite e e e de caractres 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 caractre appel newline. e e commandes d'extension du code commande nom shift out SO shift in SI escape ESC Le caractre 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 caractre escape suivi d'un a e e e e e certains nombre de caractres 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 caractres ont pour but de s parer les di rentes unit s d'information sur bandes e e e e magn tiques. Ils sont obsoltes de nos jours, les programmes d'archivage tar, cpio e e utilisant leur propre format sans faire appel a ces caractres. 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 premires commandes ont t cr es pour construire des trames de commue ee e nication entre machines reli es par des lignes synchrones. Elles sont compltement e e obsoltes 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 caractres. e La dernire 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 caractre quele e conque. Aprs 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 caractres 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 caractres 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 gre 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 caractres qui sont utilis s couramment pour r aliser la fonction d'e acee e e ment du caractre erron pr c dent : back space et delete. En fonction du caractre 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 caractre 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 caractre 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 nre 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 systme d'exploitae tion le caractre qu'il d sire pour r aliser la fonction d'e acement de caractre. e e e e
174
soh ht dc1 em
! 1 9 A I Q Y a i q y
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 '
del
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
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 trs 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 premire
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, quatrime 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 ds qu'il a d pass le stade e e e d'apprentissage du langage.
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 trs 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 trs cher si on se la e procure directement auprs 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 auprs 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.
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
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-caractre e cha^ne-litt
rale
e op
rateur e ponctuation tout caractre non blanc qui ne peut ^tre une des entit
s pr
c
dentes e e e ee
R2
183
R5
R6
chi re : un parmi
0 1
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
+ -
184
R14
constante-entire : 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 :
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
5 f
6 A
7 B
8 C
9 D
su xe-long : un parmi
l L
constante-d-
num
ration : e e identi cateur constante-caractre : e ' s
quence-de-caractres-c e e L' s
quence-de-caractres-c e e s
quence-de-caractres-c : e e caractre-c e
' '
185
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
s quence-de-caractres-s : e e caractre-s e s quence-de-caractres-s caractre-s e e e caractre-s : e n'importe quel membre du jeu de caractres source sauf le double quote " e le backslash ou le newline s quence-d- chappement e e
186
++ ? = ,
-- & : *= =
~ =
sizeof = == != = = &=
&& |=
||
=
+=
-=
^=
D.7 La ponctuation
R36
ponctuation : un parmi
* , : = ; ...
s quence-de-caractres-h : e e caractre-h e s quence-de-caractres-h caractre-h e e e caractre-h : e n'importe quel membre du jeu de caractres source sauf ou le newline e s quence-de-caractres-q : e e caractre-q e s quence-de-caractres-q caractre-q e e e caractre-q : e n'importe quel membre du jeu de caractres source sauf " ou le newline e
187
R44
. ++ --
R45 R46
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
& * + ~ !
*
R50
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
&&
||
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
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
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
;
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 constante-d- num ration e e constante-d- num ration e e quali catif-de-type :
const volatile
191
R82
* *
liste-de-quali catifs-de-types : quali catif-de-type liste-de-quali catifs-de-types quali catif-de-type liste-de-types-de-paramtres : e liste-de-paramtres e liste-de-paramtres e
...
liste-de-paramtres : e d claration-de-paramtre e e liste-de-paramtres , d claration-de-paramtre e e e d claration-de-paramtre : 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-paramtres option e
R92
192
R93
R94
initialisateur
R96
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
instruction
instruction-saut :
R110 R111
194
R112 R113 R114 R115 R116
ifndef
elif
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 parenthse-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
parenthse-g : e le caractre 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 :
195
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-paramtres e liste-de-quali catifs-de-types liste-de-sp ci cateurs-et-quali catifs e liste-de-types-de-paramtres e liste-d-expressions-paramtres 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 parenthse-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-caractres-c e e s quence-de-caractres-h e e s quence-de-caractres-q e e s quence-de-caractres-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 caractre e caractre sign e e caractre non sign e e ottant simple pr cision e ottant double pr cision e ottant quadruple pr cision e
int
long int
199
tableau de 10 entiers tableau de 5 entiers avec initialisation tableau de 80 caractres e tableau de caractres 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 caractres 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
f1, f2 ;
200
; ;
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 paramtre entier et retournant un entier e pointeur vers une fonction ayant un paramtre entier et un paramtre ottant et e e retournant un entier pointeur vers une fonction ayant un paramtre entier et ne retournant pas de valeur e pointeur vers une fonction ayant un paramtre entier et retournant un entier, avec e initialisation
int *pint = f;
fonction sans paramtre et sans valeur ree tourn e e fonction avec un paramtre entier, sans vae leur retourn e e fonction sans paramtre retournant un int e fonction avec un paramtre entier et un e paramtre ottant, retournant un int e fonction avec un paramtre entier et un e nombre variable de paramtres, retoure nant un int 201
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
Champs de bits : description du registre d' tat du mc68000. Il s'agit d'un mot de e 16 bits. Les troisime et cinquime champs e e ne portent pas de nom.
202
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 caractre. La e e d
couverte de telles erreurs ne peut donc se faire que par un examen trs attentif du e e source du programe.
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;
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
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 derrire x = 10;. e L'utilisation int t message d'erreur.
MAX ; = 10;;,
int t 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
x++ * x++
et l'op rateur e
++
Le problme 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;
207
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, trs souvent utilis
e, toutes les parenthses e e e e sont n
cessaire : e
while c = getchar != EOF ...
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;
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
Rappelons que int tab et int *t ne sont
quivalents que dans le seul cas de paramtre 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. Derrire 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 caractres G
n
ral ; Anglais : string. Suite contigue en m
moire de carac
e e e e
tres. 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
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 cupre 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 caractre, 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. Possde 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
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 paramtre e ectif G n ral ; Anglais : e ective parameter ou argument. La valeur qui est e e e pass e en paramtre a la fonction. e e paramtre formel G n ral ; Anglais : formal parameter ou parameter. Le nom d'un pae e e ramtre dans la d claration d'une proc dure ou fonction. e e e passage de paramtre G n ral ; Anglais : parameter passing. Technique de communie e e cation de paramtre entre l'appelant et une proc dure ou fonction appel e. Il existe e e e diverses faons de passer les paramtres 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 thque 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 caractre, 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 bibliothque 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 caractre 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 caractres, 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 caractre, 11 e cha^ne de caractres, voir cha^ne lit
e
t
rale e d
cimale, 11 e entire, 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
little endian, 115, 128 long, 10, 11, 89, 96, 122 lvalue, 16, 37, 40, 41
macro, 133 avec paramtres, 135 e corps de, 135 expansion de, 133, 135 pr
d
nie, 135 ee sans paramtre, 133 e main, 28, 29 malloc, 46, 109 mantisse, 13 membre de structure, 103 accs 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 paramtre 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 paramtre e passage de tableau en, voir tableau, passage en paramtre 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 caractres, 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 paramtre, 67, 68, 72 e taille de, 35 trigraphe, 11 type, 153 caractre, 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 paramtre, 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,