ansi_c99-poly

Upload: belhechmiii2623

Post on 11-Jul-2015

93 views

Category:

Documents


0 download

TRANSCRIPT

Le langage ISO C et son environnementVersions C90 et C99 Jean-Paul R IGAULTV 2.1 7 fvrier 2010

cole polytechnique de luniversit de Nice Sophia Antipolis Dpartement de sciences informatiques 930 route des Colles 06903 S OPHIA A NTIPOLIS Cedex, France Tl: +33 4 92 96 50 50 Fax: +33 4 92 96 50 55 URL : http://www.polytech.unice.fr/informatique

Avant-proposn par Dennis langage C sest impos Conu laune des annesen1960bien entenduRitchie, lepartie au succs dUnix, comme rfrence matire de programmation-systme et de ralisation de logiciel de base. Ceci est li pour systme dexploitation pour lequel C a t conu. Mais cest aussi le rsultat des vertus intrinsques du langage : sufsamment simple pour tre efcace et portable, sufsamment moderne pour tre expressif. Cette origine de langage de programmation-systme a longtemps confr C la rputation dun langage laxiste , dans lequel le typage ntait quune contrainte surajoute, presque dcorative. Les habitudes et les exigences de programmation aidant, il tait ncessaire de rendre plus rigoureux loutil. Cest cette tche que sest consacr le comit de normalisation x3j11 de lansi [2]. Le rsultat fut un langage plus sr, dot du typage fort garant dune certaine scurit de programmation, sans que cela nuise lefcacit des programmes gnrs. Cest ce langage, dit ansi C, adopt par lansi en 1989 puis par liso en 1990 (iso/iec 9899:1990) qui est actuellement la norme de fait. Nous le dsignerons simplement par C90. Cette norme a subi quelques rvisions mineures jusqu ce que lvolution parallle de la normalisation du langage C++ oblige une reprise profonde de la norme. Ceci conduit en 1999, la norme iso/iec 9899:1999 reprise par lansi en 2000. Le nouveau langage, dit C99, nest pas encore ce jour (janvier 2010) compltement implment par tous les compilateurs, bien quun large sous-ensemble le soit gnralement. Le prsent texte dcrit la fois iso C90 et iso C99, en signalant les diffrences entre les deux versions. Ces diffrences sont rsumes dans lannexe 12. Sauf mention explicite du contraire, les programmes proposs sont compatibles avec les deux versions. Pour les dtails, voir la section 1.5. Tous les exemples de cet ouvrage ont t dvelopps et tests dans un environnement tout fait habituel dans les tablissements denseignement et de recherche : stations de travail sous Linux, environnement graphique X Window. Le compilateur ansi C utlis comme rfrence est celui de gnu d initialement Richard Stallman (et la Free Software Foundation), savoir gcc [1, 23]. Les programmes devraient tre compilables avec les versions de gcc partir de 2.95 au moins mais cest seulement partir des versions 3.x que lon a la compatibilit avec C99 (option -std=c99). La compilation seffectue sous le contrle de make (version de gnu l encore). La mise au point utilise gdb [19], autre produit de la Free Software Foundation, utilis travers lune de ses interfaces avec X Window (principalement ddd [20]). Ont galement t utiliss les analyseurs dexcution gprof [21] et

V 2.1 7 fvrier 2010

1

c Jean-Paul R IGAULT

2

Avant-propos

valgrind [15]. Cet environnement de travail est dcrit dans le chapitre 10 o

sont galement introduits certains environnements intgrs de dveloppement pour C, sous Unix ou MS Windows. A Le document lui-mme a t compos laide de L TEX [10, 26] (distribution TEXLive 2009) avec les extensions Babel [7] et frenchb [5] pour traiter la typographie franaise, ainsi que xindy [14] pour gnrer lindex comportant des caractres accentus. Cet ouvrage est le fruit de prs de trente annes denseignement de C et dUnix, lEcole des mines de Paris, au cerics (Centre dEnseignement et de Recherche en Informatique, Communication et Systmes), lESSI (cole Suprieure de Sciences Informatiques de luniversit de Nice Sophia Antipolis, devenue Polytech,Nice-Sophia) et au cours de nombreuses sessions de formation continue inter- et intra-entreprises que jai animes. Je tiens donc remercier tous les collgues, tudiants et participants ces formations pour leur intrt, leur patience, et leur motivation.

Jean-Paul Rigault Professeur dinformatique Universit de Nice Sophia Antipolis Sophia Antipolis et La Roquette sur Siagne Fvrier 1993Janvier 2010

c Jean-Paul R IGAULT

V 2.1 7 fvrier 2010

Table des matiresAvant-propos Table des matires Table des gures Liste des tableaux Liste des programmes Liste des exercices 1 Introduction 1.1 Historique . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 Caractristiques de C . . . . . . . . . . . . . . . . . . . . 1.2.1 Un langage contemporain de Pascal . . . . . . 1.2.2 Un langage dimplmentation de systmes . . . 1.2.3 Un langage supportant la compilation spare . 1.2.4 Un langage incomplet. . . pour tre portable . . 1.3 Plan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.4 Notations utilises . . . . . . . . . . . . . . . . . . . . . 1.5 Compilateurs et compatibilit . . . . . . . . . . . . . . . 1.5.1 Environnement de dveloppement de rfrence 1.5.2 Version du langage C . . . . . . . . . . . . . . . 1.6 Ressources : ouvrages et sites Web sur C . . . . . . . . 1.7 Exercices du chapitre 1 . . . . . . . . . . . . . . . . . . . 2 Premiers pas 2.1 Monde, salut ! . . . . . . . . . . . . . . . . . . . . . . . 2.2 Boucle while ; entres-sorties simples . . . . . . . . . 2.3 Fonctions ; expressions ; entres-sorties . . . . . . . . 2.3.1 Exemple : calcul de la racine carre dun rel . 2.3.2 Entres-sorties formattes . . . . . . . . . . . . 2.4 Tableaux et instruction ditration . . . . . . . . . . . 2.5 Arguments du shell ; fonction rcursive . . . . . . . . 2.6 Exercices du chapitre 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 3 9 11 13 15 17 17 18 18 18 18 18 19 19 20 20 21 21 22 25 25 27 29 29 33 35 38 41

V 2.1 7 fvrier 2010

3

c Jean-Paul R IGAULT

4

TABLE DES MATIRES

3 Bases du langage 3.1 Elments lexicaux . . . . . . . . . . . . . . . . . . . . . . 3.1.1 Jeu de caractres . . . . . . . . . . . . . . . . . . 3.1.2 Structure lexicale dun chier-source . . . . . . 3.1.3 Commentaires . . . . . . . . . . . . . . . . . . . . 3.1.4 Identicateurs . . . . . . . . . . . . . . . . . . . . 3.1.5 Mots-cls . . . . . . . . . . . . . . . . . . . . . . . 3.1.6 Constantes littrales arithmtiques . . . . . . . . 3.1.7 Chanes de caractres littrales . . . . . . . . . . 3.2 Types scalaires et dclarations simples . . . . . . . . . . 3.2.1 Panorama des types de C . . . . . . . . . . . . . 3.2.2 Type vide (void) . . . . . . . . . . . . . . . . . . 3.2.3 Types de base entiers . . . . . . . . . . . . . . . . 3.2.4 Types rels . . . . . . . . . . . . . . . . . . . . . . 3.2.5 Dnitions dobjets de type de base scalaire . . 3.2.6 Types numrs . . . . . . . . . . . . . . . . . . . 3.2.7 Synonymie de types : typedef . . . . . . . . . 3.3 Oprateurs . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.1 Oprateurs arithmtiques . . . . . . . . . . . . . 3.3.2 Oprateurs relationnels et logiques . . . . . . . 3.3.3 Oprateurs bit bit . . . . . . . . . . . . . . . . . 3.3.4 Affectations . . . . . . . . . . . . . . . . . . . . . 3.3.5 Oprateurs sur les pointeurs . . . . . . . . . . . 3.3.6 Oprateurs sur les types . . . . . . . . . . . . . . 3.3.7 Oprateurs divers . . . . . . . . . . . . . . . . . 3.4 Evaluation des expressions . . . . . . . . . . . . . . . . 3.4.1 Ordre dvaluation : prcdence et associativit 3.4.2 Conversions . . . . . . . . . . . . . . . . . . . . . 3.4.3 Mlange de types dans les expressions . . . . . 3.5 Instructions et ot de contrle . . . . . . . . . . . . . . . 3.5.1 Instruction simple et bloc . . . . . . . . . . . . . 3.5.2 Instructions de slection . . . . . . . . . . . . . . 3.5.3 Instructions de boucle . . . . . . . . . . . . . . . 3.5.4 Instructions de rupture de squence . . . . . . . 3.6 Exercices du chapitre 3 . . . . . . . . . . . . . . . . . . . 4 Tableaux, structures et unions 4.1 Tableaux . . . . . . . . . . . . . . . . . . . . . . 4.1.1 Tableaux mono-dimensionnels . . . . . 4.1.2 Tableaux multi-dimensionnels . . . . . 4.1.3 Chanes de caractres . . . . . . . . . . 4.1.4 Tableaux de taille variables de C99 . . . 4.2 Structures . . . . . . . . . . . . . . . . . . . . . 4.2.1 Dnition du type et dclarations . . . 4.2.2 Structures compactes et champs de bits 4.2.3 Oprations sur les structures . . . . . . 4.2.4 Tableaux de structures . . . . . . . . . . 4.3 Unions . . . . . . . . . . . . . . . . . . . . . . . 4.3.1 Dnition du type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

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

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

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

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

43 43 43 44 45 45 46 46 48 50 50 50 51 53 53 54 55 56 56 58 60 63 64 64 65 66 66 68 70 71 71 72 75 77 79 83 83 83 86 88 88 90 90 93 94 95 96 96

c Jean-Paul R IGAULT

V 2.1 7 fvrier 2010

TABLE DES MATIRES

5

4.4

4.3.2 Oprations sur les unions . . . . . . . . . . . . . . . . . 4.3.3 Structures avec variantes . . . . . . . . . . . . . . . . . Exercices du chapitre 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

97 97 100 103 103 103 105 106 108 109 110 110 111 118 118 119 122 129 129 130 130 130 131 131 131 132 134 134 135 135 135 135 137 137 138 138 138 139 141 141 141 142 142 143 143 144

5 Pointeurs 5.1 Dclarations et oprations sur pointeurs . . . . . . . . . . . . 5.1.1 Pointeurs simples . . . . . . . . . . . . . . . . . . . . . 5.1.2 Pointeurs multiples . . . . . . . . . . . . . . . . . . . . 5.1.3 Oprations arithmtiques sur pointeurs . . . . . . . . 5.1.4 Conversions de pointeurs . . . . . . . . . . . . . . . . 5.1.5 Pointeurs et constantes . . . . . . . . . . . . . . . . . 5.2 Pointeurs sur structures et unions . . . . . . . . . . . . . . . 5.2.1 Oprateur de slection che . . . . . . . . . . . . 5.2.2 Types rcursifs . . . . . . . . . . . . . . . . . . . . . . 5.3 Pointeurs et tableaux . . . . . . . . . . . . . . . . . . . . . . . 5.3.1 Tableaux de pointeurs ; lecture des dclarations de C 5.3.2 Relations entre tableaux et pointeurs . . . . . . . . . 5.4 Exercices du chapitre 5 . . . . . . . . . . . . . . . . . . . . . . 6 Le prprocesseur ANSI C 6.1 Prtraitement des programmes C . . . . . . . . . . . . . . 6.2 Inclusion de chier . . . . . . . . . . . . . . . . . . . . . . 6.2.1 Effet de linclusion de chier . . . . . . . . . . . . 6.2.2 Recherche du chier inclure . . . . . . . . . . . 6.2.3 Utilisation de linclusion de chier . . . . . . . . . 6.3 Dnition de macros . . . . . . . . . . . . . . . . . . . . . 6.3.1 Macros sans arguments : dnition de constantes 6.3.2 Macros arguments : fonctions en ligne . . . . . 6.3.3 Dnition rcursive de macros . . . . . . . . . . . 6.3.4 Concatnation et stringication . . . . . . . . 6.3.5 Annulation de dnition : #undef . . . . . . . . . 6.3.6 Macros rserves . . . . . . . . . . . . . . . . . . . 6.4 Compilation conditionnelle . . . . . . . . . . . . . . . . . 6.4.1 Les directives de compilation conditionnelle . . . 6.4.2 Inclusion unique de chiers . . . . . . . . . . . . . 6.5 Autres directives du prprocesseur . . . . . . . . . . . . . 6.5.1 Numro de ligne : #line . . . . . . . . . . . . . . 6.5.2 Messages derreur : #error . . . . . . . . . . . . 6.5.3 Commentaire excutable : #pragma . . . . . . . . 6.6 Exercices du chapitre 6 . . . . . . . . . . . . . . . . . . . . 7 Fonctions 7.1 Arguments et valeur de retour . . . . . . . . . . . . . . 7.1.1 Type de retour dune fonction . . . . . . . . . . 7.1.2 Type des arguments dune fonction . . . . . . . 7.1.3 Mode de passage des arguments . . . . . . . . . 7.2 Dclaration, dnition et appel de fonction . . . . . . . 7.2.1 Dclaration du type dune fonction : prototype 7.2.2 Dnition dune fonction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

V 2.1 7 fvrier 2010

c Jean-Paul R IGAULT

6

TABLE DES MATIRES

7.3

7.4 7.5

7.2.3 Appel dune fonction . . . . . . 7.2.4 Fonctions en ligne de C99 . . Fonctions et pointeurs . . . . . . . . . . 7.3.1 Fonction retournant un pointeur 7.3.2 Pointeurs en argument . . . . . . 7.3.3 Pointeurs sur fonctions . . . . . La fonction main . . . . . . . . . . . . . Exercices du chapitre 7 . . . . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

145 146 146 146 147 148 151 153 155 155 156 156 158 158 158 159 161 161 162 163 164 164 165 166 167

8 Structure des programmes 8.1 Espaces de nommage . . . . . . . . . . . . . . . . . . . . . . . . 8.2 Structure des programmes C . . . . . . . . . . . . . . . . . . . 8.2.1 Compilation spare . . . . . . . . . . . . . . . . . . . . 8.2.2 Unit de compilation . . . . . . . . . . . . . . . . . . . . 8.3 Dure de vie et rgles de visibilit . . . . . . . . . . . . . . . . 8.3.1 Dure de vie . . . . . . . . . . . . . . . . . . . . . . . . . 8.3.2 Visibilit des objets . . . . . . . . . . . . . . . . . . . . . 8.3.3 Initialisation des objets . . . . . . . . . . . . . . . . . . . 8.3.4 Visibilit des fonctions . . . . . . . . . . . . . . . . . . . 8.3.5 Synthse : relation entre dure de vie et visibilit . . . 8.3.6 Autres rgles de visibilit . . . . . . . . . . . . . . . . . 8.4 Programmation modulaire en C . . . . . . . . . . . . . . . . . 8.4.1 Notion de module . . . . . . . . . . . . . . . . . . . . . 8.4.2 Objets globaux trouvs dans une interface de module 8.4.3 Exemple dorganisation modulaire . . . . . . . . . . . . 8.5 Exercices du chapitre 8 . . . . . . . . . . . . . . . . . . . . . . .

9 La bibliothque standard 171 9.1 lments gnraux . . . . . . . . . . . . . . . . . . . . . . . . . 171 9.1.1 Assertions : . . . . . . . . . . . . . . . . . 171 9.1.2 Codes derreur : . . . . . . . . . . . . . . . 171 9.1.3 Dnitions communes : . . . . . . . . . . 171 9.1.4 Utilitaires gnraux : . . . . . . . . . . . 172 9.2 lments numriques . . . . . . . . . . . . . . . . . . . . . . . . 172 9.2.1 Boolens : . . . . . . . . . . . . . . . . . 172 9.2.2 Types entiers : . . . . . . . . . . . . . . . 172 9.2.3 Conversion des types entiers : . . . . 172 9.2.4 Environnement pour calcul en nombres rels : 172 9.2.5 Nombres complexes : . . . . . . . . . . 173 9.3 Fonctions mathmatiques . . . . . . . . . . . . . . . . . . . . . 173 9.3.1 Bibliothque mathmatique de base : . . . 173 9.3.2 Bibliothque mathmatique gnrique : 173 9.4 Caractres et chanes de caractres . . . . . . . . . . . . . . . . 173 9.4.1 Manipulation de caractres : . . . . . . . . 173 9.4.2 Manipulation de chanes de caractres : 173 9.4.3 Manipulation de caractres tendus: . . 174 9.4.4 Manipulation de chanes de caractres tendus : 174 9.4.5 Localisation : . . . . . . . . . . . . . . . . 174 9.5 Entres-sorties : . . . . . . . . . . . . . . . . . . . 174

c Jean-Paul R IGAULT

V 2.1 7 fvrier 2010

TABLE DES MATIRES

7

9.6

Divers 9.6.1 9.6.2 9.6.3 9.6.4 9.6.5

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fonctions nombre variable darguments : Date et heure : . . . . . . . . . . . . . . . . . Traitement dvnements : . . . . . . . . Points de reprise : . . . . . . . . . . . . . Notation alternative de certains oprateurs : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

174 175 175 175 175 176 177 177 178 178 179 180 182 182 183 184 184 185 189 189 189 189 189 189 189 189 189 189 189 189 189 189 189 191 191 191 191 193 195 203

10 Environnement de dveloppement 10.1 Compilateurs . . . . . . . . . . . . . . . . . . . . . . 10.2 Dveloppement traditionnel sous Unix . . . . . . . 10.2.1 dition de source . . . . . . . . . . . . . . . . 10.2.2 Loutil make . . . . . . . . . . . . . . . . . . . 10.2.3 Mise au point avec gdb et compagnie . . . . 10.2.4 Outils de documentation . . . . . . . . . . . 10.3 Environnements intgrs de dveloppement . . . . 10.3.1 Environnements multi-plateformes . . . . . 10.3.2 Environnements spciques Unix . . . . . 10.3.3 Environnements spciques MS Windows 10.4 Remarque nale . . . . . . . . . . . . . . . . . . . . . 11 Extensions avances de C99 11.1 Prprocesseur . . . . . . . . . . . . . . . . . . . . . 11.1.1 Macros prdnies . . . . . . . . . . . . . . 11.1.2 Macros nombre variable darguments . . 11.2 langage de base . . . . . . . . . . . . . . . . . . . . 11.2.1 Nom de la fonction courante : __func__ . 11.2.2 Pointeurs restreints : restrict . . . . . . 11.2.3 Tableaux . . . . . . . . . . . . . . . . . . . . 11.3 Bibliothque standard . . . . . . . . . . . . . . . . 11.3.1 Fichiers dentte . . . . . . . . . . . . . . . 11.3.2 Type boolen . . . . . . . . . . . . . . . . . 11.3.3 Types entiers tendus . . . . . . . . . . . . 11.3.4 Nombres complexes . . . . . . . . . . . . . 11.3.5 Manipulation des caractres multiples . . 11.3.6 Rels en virgule ottante . . . . . . . . . . . . . . . . . . . . . . . .

12 C traditionnel, iso C90, iso C99 et C++ 12.1 Diso C90 C traditionnel . . . . . . . . . . . . . . . . . . . . . 12.2 Diso C90 iso C99 . . . . . . . . . . . . . . . . . . . . . . . . . 12.3 Diso C90 ou iso C99 C++ . . . . . . . . . . . . . . . . . . . . Bibliographie Glossaire Index

V 2.1 7 fvrier 2010

c Jean-Paul R IGAULT

8

TABLE DES MATIRES

c Jean-Paul R IGAULT

V 2.1 7 fvrier 2010

Table des gures2.1 2.2 3.1 4.1 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 5.10 8.1 8.2 8.3 10.1 10.2 10.3 10.4 10.5 10.6 10.7 10.8 7.1 Algorithme de tri par insertion . . . . . . . . . . . . . . . . . . Arbre de calcul rcursif de fibo(4) . . . . . . . . . . . . . . Reprsentation dune chane de caractres littrale . . . . . . . Exemple de champs de bits . . . . . . . . . . . . . . . . . . . . Pointeur simple . . . . . . . . . . . . . . . . . . . . . . . . . . . Pointeur double . . . . . . . . . . . . . . . . . . . . . . . . . . . Liste simplement chane : simple_list.h . . . . . . . . . . Insertion dans une liste avec un simple pointeur . . . . . . . . Insertion dans une liste avec un double pointeur . . . . . . . . Relation entre pointeurs et tableaux mono-dimensionnels en C Tableau multi-dimensionnel et tableau de pointeurs . . . . . . Liste doublement chane avec cellule de garde et rebouclage Structure dun arbre binaire . . . . . . . . . . . . . . . . . . . . Un exemple darbre binaire . . . . . . . . . . . . . . . . . . . . Compilation spare et units de compilations . . . . . . . . . Visibilit et dure de vie : quelques exemples . . . . . . . . . . Organisation dun module en C . . . . . . . . . . . . . . . . . . XEmacs luvre . . . . . . . . . . . . . . . . . . . . . . . . . ddd (et gdb) luvre . . . . . . . . . . . . . . . . . . . . . . Eclipse en mode dition/compilation de C/C++ . . . . . . . Eclipse en mode mise au point de C/C++ . . . . . . . . . . . Encore un IDE multiplateformes, Code::Blocks . . . . . . . . Un IDE multiplateformes lger, CodeLite . . . . . . . . . . . Visual Studio 2008 en mode dition/compilation de C/C++ Visual Studio 2008 en mode mise au point de C/C++ . . . . . . . . . . . . 37 41 49 93 104 106 112 113 118 120 122 124 126 127 157 163 165 179 181 183 184 185 186 187 187 197

Chane de compilation C . . . . . . . . . . . . . . . . . . . . . .

V 2.1 7 fvrier 2010

9

c Jean-Paul R IGAULT

10

TABLE DES FIGURES

c Jean-Paul R IGAULT

V 2.1 7 fvrier 2010

Liste des tableaux3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 8.1 Jeu de caractres ASCII . . . . . . . . . . . . . . . Mots-cls de C . . . . . . . . . . . . . . . . . . . . Mots-cls supplmentaires de Cnew . . . . . . . Squences dchappement pour les caractres . Panorama des types de C . . . . . . . . . . . . . Sous-types de int . . . . . . . . . . . . . . . . . Liste des oprateurs de C . . . . . . . . . . . . . Prcdence et associativit des oprateurs de C Relations entre dure de vie et visibilit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 46 46 47 51 52 57 67 162

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

V 2.1 7 fvrier 2010

11

c Jean-Paul R IGAULT

12

LISTE DES TABLEAUX

c Jean-Paul R IGAULT

V 2.1 7 fvrier 2010

Liste des programmes2.1 2.2 2.3 2.4 2.5 2.6 2.7 3.1 3.2 3.3 3.4 3.5 3.6 4.1 4.2 4.3 4.4 5.1 5.2 5.3 5.4 7.1 7.2 8.1 8.2 8.3 8.4 8.5 8.6 8.7 8.8 Le programme hello, world original . . . . . . . . . Le programme hello, world localis en franais . . . Copie de chiers . . . . . . . . . . . . . . . . . . . . . . Calcul de la racine carre dun nombre rel . . . . . . . Programme simple de lecture de scalaires . . . . . . . . Tri par insertion dune suite dentiers . . . . . . . . . . Calcul du terme de rang n de la suite de Fibonacci . . Remplacement des ns de ligne par un blanc . . . . . . Longueur utile dune chane de caractres . . . . . . . Copie de chanes de caractres . . . . . . . . . . . . . . Calcul du pgcd de deux entiers . . . . . . . . . . . . . . Pathologie du dcalage . . . . . . . . . . . . . . . . . . . Manipulation de bits . . . . . . . . . . . . . . . . . . . . Produit scalaire de deux vecteurs . . . . . . . . . . . . . Transposition dune matrice . . . . . . . . . . . . . . . . Tableaux dimension variable de C99 . . . . . . . . . . Structure avec variante (en C99) . . . . . . . . . . . . . Liste dentiers : dnition du type . . . . . . . . . . . . Liste dentiers : insertion par ordre croissant . . . . . . Liste dentiers : programme principal . . . . . . . . . . Insertion dans une liste avec un seul (double) pointeur Les pointeurs sur fonction dans tous leurs tats . . . . La commande echo modie . . . . . . . . . . . . . . . Espaces de nommage en C . . . . . . . . . . . . . . . . . Visibilit des objets locaux . . . . . . . . . . . . . . . . . Visibilit et dure de vie : fic1.c . . . . . . . . . . . . Visibilit et dure de vie : fic2.c . . . . . . . . . . . . Visibilit des noms de type en ansi C . . . . . . . . . . Spcication du module pile dentiers . . . . . . . . Corps du module pile dentiers . . . . . . . . . . . . Utilisation du module pile dentiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 26 27 30 34 36 39 47 49 50 59 61 62 84 87 89 98 112 114 116 117 150 152 156 159 163 163 164 167 168 169

V 2.1 7 fvrier 2010

13

c Jean-Paul R IGAULT

14

LISTE DES PROGRAMMES

c Jean-Paul R IGAULT

V 2.1 7 fvrier 2010

Liste des exercices1.1 1.2 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 3.1 3.2 3.3 3.4 3.5 4.1 4.2 4.3 4.4 4.5 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 7.1 7.2 8.1 8.2 8.3 Vrications prliminaires . . . . . . . . . . . . . . Accs la documentation . . . . . . . . . . . . . . Mise en route . . . . . . . . . . . . . . . . . . . . . Copie de chiers . . . . . . . . . . . . . . . . . . . La commande iota . . . . . . . . . . . . . . . . . . Minimum et maximum dun ensemble dentiers . Conversion Celsius-Farenheit . . . . . . . . . . . Drcursiver le calcul de la suite de Fibonacci Amlioration du calcul de la racine carre . . . . Mauvais format . . . . . . . . . . . . . . . . . . . . Nombre de bits 1 dans un octet . . . . . . . . . . Nombre de caractres, mots et lignes dun texte . valuation dun polynme . . . . . . . . . . . . . . Nombres premiers . . . . . . . . . . . . . . . . . . Quelques oprations non portables . . . . . . . . . Manipulation de bits . . . . . . . . . . . . . . . . . Calcul matriciel simple . . . . . . . . . . . . . . . . Recherche en table . . . . . . . . . . . . . . . . . . Oprations sur les dates . . . . . . . . . . . . . . . Gestion de liste de contacts . . . . . . . . . . . . . Liste trie simplement chane . . . . . . . . . . . Liste trie doublement chane . . . . . . . . . . . Manipulation de chanes de caractres . . . . . . . Tri dun tableau de pointeurs . . . . . . . . . . . . Commande fgrep . . . . . . . . . . . . . . . . . . . Arbre binaire . . . . . . . . . . . . . . . . . . . . . Recherche dichotomique . . . . . . . . . . . . . . . Pathologie des pointeurs . . . . . . . . . . . . . . . Intgration par la mthode des trapzes . . . . . . Efcacit des fonctions inline . . . . . . . . . . . . Modication de limplmentation des piles . . . . File fifo . . . . . . . . . . . . . . . . . . . . . . . . Du module au type abstrait . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 23 41 41 42 42 42 42 42 42 79 80 80 80 80 100 100 100 101 101 122 123 123 125 126 126 127 127 153 153 167 167 167

V 2.1 7 fvrier 2010

15

c Jean-Paul R IGAULT

16

LISTE DES EXERCICES

c Jean-Paul R IGAULT

V 2.1 7 fvrier 2010

Chapitre 1

Introduction1.1 HistoriqueLe langage C trouve son origine au dbut des annes 1970, lorsque Dennis Ritchie rejoint Ken Thomson aux Bell Laboratories. Ce dernier a dj dni en 1970 le langage B, driv de BCPL, pour implmenter de manire portable le systme dexploitation quil vient dinventer et quil a dnomm Unix. En 1972, C voit le jour et est utilis pour rcrire compltement le noyau dunix (en un t!). Le langage recevra une dnition de rfrence par la publication du livre de Brian Kernighan et Dennis Ritchie en 1978 [16]. Le langage dcrit dans ce livre, avec quelques extensions ultrieures (affectation et passage en arguments de structures et dunions, introduction du type void), constitue ce quil est convenu dappeler le C traditionnel . Le dveloppement considrable de C, dabord entrain par celui dUnix puis relativement autonome, rendit ncessaire une normalisation qui fut entreprise partir de 1983 par le comit x3j11 de lansi 1 . Les travaux se terminrent n 1988, par une norme ansi reprise par ieee puis par liso (norme iso-9899). La deuxime dition du livre de Kernighan et Ritchie [17] dcrit le langage ainsi normalis. La compatibilit arrire a t lun des soucis de lansi, et la plupart des programmes crits en C traditionnel peuvent tre recompils avec ansi C. Mais, sans rien changer la philosophie du langage, ansi C a apport de nombreuses amliorations allant la fois dans le sens de la scurit de programmation (typage fort, meilleure rigueur smantique) et dans celui de la portabilit (par exemple dnition de la bibliothque dexcution minimale). La version C99 est galement largement compatible avec iso C90. Malheureusement de nombreux compilateurs C ne la supporte pas encore compltement. Ainsi, parmi les compilateurs majeurs, gcc 3 et 4 supportent lessentiel de C99, mais pas la totalit et Microsoft Visual Studio 2005 (C++ version 8) et 2008 (version 9) ne prtendent mme pas supporter cette norme mme sils en ont des parties du fait de leur compatibilit C++. Bref, C99 nest pas encore trs rpandu dix ans aprs sa normalisation ! Cest pourquoi tous les programmes donns ici, sauf mention spciale, sont compatibles avec C90 aussi bien quavec C99.1. American National Standards Institute

V 2.1 7 fvrier 2010

17

c Jean-Paul R IGAULT

18

1. Introduction

1.2 Caractristiques de C1.2.1 Un langage contemporain de PASCALC a t conu peu prs en mme temps que des langages comme Pascal et il rete donc ltat de lart de lpoque. Cest donc un langage qui supporte la programmation structure (on dit aussi procdurale). Il dispose en particulier de types structurs dnissables par lutilisateur, analogues aux records de Pascal.

1.2.2 Un langage dimplmentation de systmesCependant C traditionnel garde de son origine de langage dimplmentation de systme dexploitation un certain nombre de caractristiques de bas niveau : instructions proches du langage-machine, manipulations dadresses au travers de pointeurs, typs certes, mais non controls, typage laxiste permettant pratiquement tous les mlanges. . . du moment que le compilateur est capable de gnrer du code ! partage de la mme zone de mmoire par des objets de types diffrents (unions). . . ansi C a ragit contre la plupart de ces licences tout en prservant la souplesse indispensable un langage de programmation-systme. Les possibilits prcdentes et parfois dangereuses de C restent utilisables en ansi C condition dtre explicites.

1.2.3 Un langage supportant la compilation spareConu pour raliser des programmes dont la taille pouvait tre relativement importante (un systme dexploitation tout entier), C se devait de supporter demble la compilation spare et la modularit. Cependant lapproche de la modularit est la mme dans les versions iso quen C traditionnel. Elle reste donc assez archaque si on la compare aux langages modernes comme Ada ou certains langages objets.

1.2.4 Un langage incomplet. . . pour tre portableLa portabilit est en fait lorigine de C : cest une des motivations pour crire le noyau dun systme dexploitation avec un langage de haut niveau. Le rsultat est un succs, et ce malgr lexistence des caractristiques de bas niveau dj mentionnes (1.2.2). Mais pour assurer cette portabilit les concepteurs du langage ont d en exclure toutes les fonctionnalits qui leur paraissaient trop dpendantes des machines ou des systmes. Cest ainsi, par exemple, que C ne comporte aucune instruction dentre-sortie, de manipulation de chanes de caractres, de gestion du paralllisme ou de la concurrence, ni de communication entre processus. Cette approche de la portabilit peut apparaitre paradoxale. Aprs tout, un langage comme Java assure sa portabilit de manire exactement inverse, en

c Jean-Paul R IGAULT

V 2.1 7 fvrier 2010

1.3. Plan

19

rednissant de manire indpendante de la plate-forme les fonctions du systmes dexploitation (entres-sorties, gestion de chiers, de mmoire, gestion des threads , etc.), et jusquau processeur lui-mme (grce la machine virtuelle) ! Cependant, noublions pas que C est lorigine un langage conu pour raliser des systmes dexploitation ce qui, nous lavons vu, lamne proposer des fonctionnalits de bas niveau . Conjuger portabilit et bas niveau conduit donc ce minimalisme de C. Par ailleurs, lpoque, un des slogans favoris tait small is beautiful ! Ces fonctionnalits indispensables sont dlgues un bibliothque dexcution standard (la clbre standard library). ansi C a fait un gros effort pour normaliser cette bibliothque, au moins dans ses fonctionnalits minimales.

1.3 PlanLe chapitre 2 permet, travers une srie dexemples simples, de faire un tour rapide du langage C. Les chapitres 3, 4 et 5 reprennent en dtail respectivement la description du langage de base (types, oprateurs et expressions, instructions de contrle), celle des agrgats (tableaux, structures et unions) et enn celle des pointeurs. Les chapitres 7 et 8 dcrivent en dtail la notion de fonction et la structure des programmes. Y est galement aborde la programmation modulaire en C. Le prprocesseur ansi C est tudi en dtail au chapitre 6. Lenvironnement dexcution avec une description succinte des bibliothques standards est lobjet du chapitre 9, et lenvironnement de dveloppement celui du chapitre 10. Enn le chapitre 11 rsume les extensions introduites par C99 et qui nont pas t traites dans le reste du texte. Quant au chapitre 12 il synthtise les diffrences entre C traditionnel , C90, C99 et C++.

1.4 Notations utilisesLes noms de systmes, langages ou organisations sont composs en petites capitales : Linux, Algol, iso. . . Les noms propres de personnes sont galement en petites capitales, avec des majuscules, comme pour Dennis Ritchie, Richard M. Stallman. . . Nous utilisons une police oblique pour les mots anglais ou techniques non traduits, comme par exemple integer ou lvalue. La police grasse sans empattement sert pour les noms de commandes au shell comme ls ou gcc. Les (brefs) extraits de programme insrs dans le texte sont composs avec une police chasse fixe et les identicateurs sont en police grasse, comme danswhile (*p1 != \0) *p2++ = *p1++;

Dans ces extraits, les identicateurs composs en police oblique, comme instruction et condition dans lextrait suivant, sont remplacer par des expressions ou instructions terminales :while (condition) instruction

V 2.1 7 fvrier 2010

c Jean-Paul R IGAULT

20

1. Introduction

Les programmes complets (ceux qui gurent dans la Liste des programmes, A page 13) sont afchs par le paquettage L TEX listings. Ils sont donc dcors syntaxiquement pour mettre en vidence les mots-cls, chanes de caractres littrales, constantes, etc. En outre, les lignes sont numrotes. Le programme 2.1 du chapitre suivant en fournit un exemple. On pourra stonner de ne pas trouver de caractres accentus dans ces programmes. Cela est d au fait que jutilise le codage des caractres Unicode (utf-8 pour tre prcis) qui nest correctement A support ni par le paquettage listings de L TEX ni par les compilateurs C90. En revanche, nous verrons en 11.3.5 quun certain support est prvu en C99. Lorsque lon prsente un exemple dinteraction entre lutilisateur et le systme, on suppose toujours que cette interaction a lieu sous un des shell dUnix (ou de Linux, de Cygwin. . .). La syntaxe suppose le shell du Steve Bourne sh ou lun de ses descendants comme bash, ksh, ou zsh. . . (personnellement jutilise zsh). Linteraction est prsente comme suit :% ls -F Stack CVS/ Makefile % Stack* Stack.c Stack.h Stack_main.c

Ici % reprsente la chane de sollicitation (le prompt) envoy par le shell, le texte en oblique gras (comme ls -F Stack) est celui entr par lutilisateur, et le texte droit (comme CVS/) celui mis par le systme. Les caractres de contrle comme ctrl-d (simulation de n de chier au terminal sous Unix) sont reprsents sous la forme usuelle utilisant le prxe ^ (D). Par ailleurs lorsque ces exemples utilisent des accents, ils supposent un systme Unix ou Linux correctement congur. Ainsi la variable denvironnment LANG doit prciser un encodage 8 bits comme iso88591, iso88591@euro, ou utf8. Par exemple, la valeur de ma propre variable LANG est en_US.UTF-8 (je naime pas avoir les messages du systme en franais !).

1.5 Compilateurs et compatibilit1.5.1 Environnement de dveloppement de rfrenceLenvironnement de dveloppement de rfrence utilis dans ce document est le suivant (dcembre 2010) : processeur intel Core Duo 2.6 Mhz quad, mmoire centrale 4 Goctets, 2 disques durs 500 Goctets (SATA, 7200 tr/min) ; systme dexploitation Linux (Fedora11, noyau 2.6.30, glibc 2.10), systmes de chiers ext3 ; environnement graphique X Window 11 et gestionnaire gnome 2.26 ; diteur emacs 23.1, gnu make 3.81, mise au point avec gdb 6.8 ; compilateur gcc 4.4.3. Les programmes se compilent et fonctionnent galement sous MacOs X (versions Leopard et Snow Leopard) avec le compilateur fourni par Apple (gcc4.2) comme avec les compilateurs gcc-4.4.x. En ce qui concerne Microsoft Windows, les programmes ont t compils et excuts avec succs en utilisant Cygwin et gcc-3.4), et aussi avec les compilateurs de Microsoft Visual Studio 2005 et 2008 (en mode C++). . Voir le chapitre 10 pour les dtails.

c Jean-Paul R IGAULT

V 2.1 7 fvrier 2010

1.6. Ressources : ouvrages et sites Web sur C

21

1.5.2 Version du langage CCe document dcrit la fois les normes iso C90 et iso C99, ce qui veut dire que, sauf mention explicite, le texte sapplique aux deux versions. Lorsque lon veut attirer lattention sur une proprit du langage C diffrente entre C90 et C99, on utilise une marque marginale comme pour ce paragraphe. Si toute une section ne sapplique qu C99, son titre est ainsi. Enn, certaines extensions lourdes de C99 ne seront pas utilises dans ce cours, mais elles sont rsumes au chapitre 11. Le compilateur gcc 4.4 utilis supporte presque entirement (voir [22]) la norme C99 et cest dans ce mode quil est utilis ici (option -std=c99). Cependant, la plupart des exemples de programmes donns dans ce document nutilisent pas sauf mention explicite les fonctionnalits idiosyncratiques de C99 et doivent donc tre compilables galement avec un compilateur C90 (option -ansi de gcc) ou un compilateur C++ raisonnable (comme g++ ou Microsoft Visual C++ dj mentionns). Pour compiler on utilise ici systmatiquement la commande make. Beaucoup de programmes tant rduits une seule unit de compilation (un seul chier source .c), on peut utiliser make sous Unix sans avoir besoin de Makefile. Il suft de dnir les deux variables denvironnement CC et CFLAGS, par exemple en plaant dans lun des chiers dinitialisation du shell 2 :export CC=gcc export CFLAGS="-g -std=c99 -Wall"

C99

Ensuite, pour compiler un programme tenant tout entier dans un seul chier source, disons prog.c, il suft dexcuter la commande make prog qui va produire (sil ny a pas derreur) un chier excutable de mme nom que le source mais sans lextension .c (donc ici, prog), quil sufra dexcuter son tour :% make prog % prog ... affichage des resultats de prog ...

Lorsquune Makefile est ncessaire, elle est dcrite dans le texte. En outre on trouvera des complments sur make en 10.2.2.Avertissements (warnings) lors de la compilation

Noter que nous compilons toujours avec tous les warnings activs (option de compilation -Wall). Un programme C doit tre exempt de tels warnings. Certains peuvent vous sembler sans consquence, mais il faut beaucoup de discernement et dexprience pour en tre sr.

1.6 Ressources : ouvrages et sites Web sur CLe langage C a donn lieu une abondante littrature et je ne donnerai ici que quelques titres parmi ceux qui me paraissent les plus recommandables. En tte vient bien sr louvrage des inventeurs du langage, Brian Kernighan et Denis Ritchie, dans sa seconde dition (ansi) en anglais [17] ou dans sa traduction franaise [18]. Cest un livre assez court compar la plupart des2. selon les cas et les shells, cest un chier comme .profile, .zshenv, .login, .bashrc... prsent dans votre rpertoire initial (home directory)

V 2.1 7 fvrier 2010

c Jean-Paul R IGAULT

22

1. Introduction

autres et qui va directement lessentiel. Il contribue aussi promouvoir un certain style de programmation bien dans la philosophie du small is beautiful chre Unix. Bref, cet ouvrage est hautement recommand. Bien entendu, sil couvre la norme ansi 89 (iso C90), il naborde absolument pas les extensions de C99. Pour cette dernire version de la norme, il existe quelques ouvrages rcents comme celui de Kochan [8] ou encore, si vous aimez les gros livres trs dtaills, de Prata [3]. Parmi les (nombreux) ouvrages directement crits en franais, citons louvrage de Claude Delannoy [12], auteur renomm pour sa pdagogie, ainsi que le livre trs complet dAchille Braquelaire [27]. Ce dernier dborde le cadre de ce cours puisquil prsente aussi la programmation-systme avec lapi Posix (cest--dire avec Unix ou ses clones comme Linux). Un grand nombre de sites sur lInternet ont des sections consacrs au langage C. En particulier le trs intressant site franais developpez.com [29] et son forum [28] permettent dchanger des informations couvrant de nombreux langages et systmes, dont C et C++. Invitables dans tous ces sites interactifs, les interventions incomptentes, les jugements premptoires et non motivs, mmes les dbuts dengueulades, sans parler des orthographes douteuses sy rencontrent beaucoup moins quailleurs, favorisant des informations prcises et utiles. Hberg par developpez.com, le site de Nicolas Joseph [6] fournit dexcellents rsums sur la compatibilit entre C90 et C99, ainsi que des conseils de programmation, des piges viter et des liens sur dautres ressources concernant C. Si, au del de C, vous dcidez de vous intresser C++, le livre de linventeur de ce langage, Bjarne Stroustrup, dans sa troisme dition [24] peut tre un dbut moins que vous prfriez une approche plus progressive avec le rcent livre du mme Stroustrup, vritable introduction la programmation en gnral [25] ou encore avec [11, 4]. En ce qui concerne la compatibilit entre C(90 ou 99) et C++, on peut consulter lexcellent rsum d David Tribble [9].

1.7 Exercices du chapitre 1Exercice 1.1 (Vrications prliminaires) Dterminez le compilateur C dont vous disposez. Sous Unix/Linux ou Cygwin, cela a des chances dtre gcc. Dterminez-en la version (commande gcc -v). Il serait bon que ce soit 3.4 ou 4.x pour avoir la compatibilit avec le standard C99. Vrier aussi la disponibilit dun outil de mise au point comme gdb ou lune de ses formes graphiques kdbg, xxgdb, ddd. . .

Choisissez votre diteur. vriez quil est correctement congur, quil sait mettre en valeur (par changement de polices ou de couleurs) la syntaxe du langage. Explorez la manire dont il collabore avec make, vous permettant de lancer vos compilations et surtout de rcuprez les messages derreurs sans quitter lditeur. Si votre diteur na pas cette dernire fonctionnalit, changezen avant quil ne soit trop tard ! Si vous dcidez dutiliser un environnement intgr de dveloppement (ide) comme kdevelop ou eclipse, apprenez lutiliser correctement, dnir et grer des projets, interagir avec make et les dbogeurs.

c Jean-Paul R IGAULT

V 2.1 7 fvrier 2010

1.7. Exercices du chapitre 1

23

Si vous tes sous MS Windows et que vous dcidez dutilisez Microsoft Visual Studio, sachez que vous disposerez dun excellent ide condition de savoir lutiliser. Laide en ligne sur les bibliothques C est galement de haute qualit 3 . Malheureusement, avec Visual Studio, vous naurez pas un compilateur rellement compatible avec la norme C99. Par ailleurs il vous faudra au moins la version 2005. Une autre possibilit sous MS Windows est dapprendre utiliser lun des multiples ide disponibles et qui sont souvent connects un compilateurs gcc: voir 10.Exercice 1.2 (Accs la documentation) Elle doit se faire en ligne. Tout systme de type Unix dispose de la clbre commande man qui permet daccder la descriptions des commandes shell, des fonctions de bibliothque, des

chiers systme, etc. Apprenez lutiliser correctement (faites donc la commande man man), elle ou lune de ses interfaces comme info ou autre. Notez que les fonctions des bibliothques standards de C se trouvent dans la section 2 ou 3 du manuel. Vous pouvez galement recourir un site Web fournissant une description dtaille de la bibliothque standard. Il y en a un grand nombre que Google se fera un plaisir de vous indiquer. Un bon point de dpart, comme souvent, est Wikipdia 4 .

3. http://msdn2.microsoft.com/en-us/library/ 4. http://en.wikipedia.org/wiki/C_standard_library. Cest la version en anglais, beaucoup plus complte que celle en franais.

V 2.1 7 fvrier 2010

c Jean-Paul R IGAULT

24

1. Introduction

c Jean-Paul R IGAULT

V 2.1 7 fvrier 2010

Chapitre 2

Premiers paschapitre rapidement en unes des Ceprincipalespasselangagelangage etrevue quelques en dtail caractristiques du C qui seront reprises par la suite. Il constitue un tour rapide du introduit au passage quelques fonctions dentre-sortie utiles. Le but est de permettre au lecteur de rdiger rapidement quelques programmes simples. La prsentation utilise une suite dexemples assez classiques : lun des programmes les plus simples possibles, avec le clbre "hello, world!" ; un programme de copie de chier, introduisant la notion de boucle (ici une boucle while) et des fonctions simples dentre-sortie ; un programme introduisant les notions de fonction, dexpression arithmtique et dentre-sortie formatte (calcul de la racine carre dun nombre rel) ; un programme de tri par insertion an dintroduire la boucle for et la notion de tableau ; enn le calcul du terme de rang n de la suite de Fibonacci, prsent comme un exemple de fonction rcursive.

2.1 Monde, salut !Depuis la premire dition du livre de Kernighan et Ritchie [16], de nombreux ouvrages sur C dbutent par un programme trs simple, pratiquement toujours le mme. Il nest absolument pas dshonorant de sacrier une tradition si bien tablie. Le programme 2.1 est donc le clbre hello, world! . Programme 2.1 Le programme hello, world original/***** Fichier: hello.c *****/ #include 5

int main() { printf("hello, world!\n"); }

V 2.1 7 fvrier 2010

25

c Jean-Paul R IGAULT

26

2. Premiers pas

On peut en prfrer la version franaise en 2.2. Programme 2.2 Le programme hello, world localis en franais/***** Fichier: salut.c *****/ #include 5

int main() { printf("Monde, salut !\n"); }

Ce programme (prenons la version amricaine 2.1 par exemple) est compos de trois entits : 1. un commentaire (entre /* et */), 2. une directive au prprocesseur (la ligne dbutant par #), 3. une dnition de fonction constitue de toutes les lignes suivantes. La directive au prprocesseur#include

permet dimporter les dclarations des fonctions dentre-sortie de la bibliothque standard, cest--dire les prototypes de ces fonctions qui prcisent les types des arguments et le type de retour. Ici, une seule fonction de bibliothque est directement utilise : printf. Les directives au prprocesseur sont reconnaissables au dise (#) qui doit tre le premier caractre de la ligne (autre quun blanc ou une tabulation horizontale). Le nom de cette directive (include) voque son mcanisme : il sagit dune inclusion textuelle du chier stdio.h. Les piquants () indiquent que ce chier est chercher dans des rpertoires par dfaut dpendant de linstallation (ici sans doute /usr/include). Le programme ne comporte quune seule fonction, nomme main. Par convention expresse, la fonction main est celle par laquelle commence lexcution dun programme C. La dnition de la fonction main comporte lentte de la fonctionint main()

qui en prcise le nom et surtout la signature : ici une fonction sans argument type de retour entier 1 (int pour integer). Le corps de la fonction main est un bloc, reconnaisable au fait quil est encadr par une paire daccolades :{ printf("hello, world!\n"); }

Ici, ce bloc ne comporte quune instruction simple, linvocation (ou lappel) de la fonction printf avec un argument effectif qui est une chane de caractres littrale "hello, world!n". Cette fonction afche la chane de caractres sur la sortie standard (stdout), suivie dune n de ligne reprsente par la1. La signature de la fonction main est impose parmi un nombre de choix limit (voir 7.4).

c Jean-Paul R IGAULT

V 2.1 7 fvrier 2010

2.2. Boucle while ; entres-sorties simples

27

squence \n (newline). Noter le point-virgule nal : toute instruction simple et toute dclaration de C se termine par un point-virgule. Supposons que ce programme ait t saisi, laide dun diteur de texte quelconque, dans le chier hello.c. Il ne reste plus qu le compiler, par exemple en utilisant la commande make (que nous considrons comme la seule commande de compilation sous Unix 2 ) :% make hello gcc -g -std=c99 -Wall -o hello hello.c %

puis excuter le chier binaire produit (qui a t nomm hello par loption -o de la commande prcdente) :% hello hello, world! %

2.2 Boucle while ; entres-sorties simplesLe programme 2.3 lit chaque caractre de son entre standard (stdin) et le copie tel quel sur sa sortie standard (stdout). Programme 2.3 Copie de chiers/***** Fichier: copy.c *****/ #include 5

int main() { int c; while ((c = getchar()) != EOF) putchar(c); return 0; }

10

La premire ligne du corps de la fonction main est une dnition de variable locale :int c;

Le nom de la variable est c et son type est int pour integer, cest--dire entier (sign). Le reste du corps de main est une boucle while qui a la structure suivante :while (condition) corps2. Pour la conguration de make, voir le chapitre 10. Ici, les rgles par dfaut doivent sufre si les variables denvironnement ont t correctement positionnes comme indiqu en 1.5.2; il ny a pas besoin de dnir de Makefile.

V 2.1 7 fvrier 2010

c Jean-Paul R IGAULT

28

2. Premiers pas

Une telle boucle excute son corps, constitu par une instruction simple ou un bloc, tant que la condition, qui est une expression entire quelconque, a une valeur non nulle. La condition est value et teste avant chaque itration, y compris la premire. La boucle while est une des trois formes de boucles dont dispose C (avec for et do ... while voir 3.5.3). Ici la condition(c = getchar()) != EOF

est une expression relationnelle car != est loprateur dingalit. Dans a != b les deux expressions a et b sont values et compares : si elle sont diffrentes, la valeur de lexpression a != b est 1, sinon cest 0 3 . C possde aussi loprateur dgalit == (attention ==, deux signes = colls !), ainsi que les oprateurs de comparaison (=). Loprande droit de != est la valeur prdnie EOF (voir ci-aprs). Loprande gauchec = getchar()

est une expression daffectation, = tant loprateur daffectation. La valeur de lexpression de droite devient la nouvelle valeur de lobjet rfrenc par lexpression de gauche (ici la variable c). La valeur de lexpression daffectation elle-mme est la nouvelle valeur de lobjet en partie gauche. Donc(c = getchar()) != EOF

invoque la fonction getchar, copie sa valeur de retour dans la variable c, et compare cette nouvelle valeur de c la constante EOF. La boucle while sera excute tant que cette comparaison donnera une valeur non nulle (cest--dire tant que la nouvelle valeur de c nest pas EOF). Noter que les parenthses sont indispensables pour grouper laffectation, sinonc = getchar() != EOF

sinterprte commec = (getchar() != EOF)

cause de la prcdence des oprateurs (voir 3.4.1). Une expression comme(c = getchar()) != EOF

illustre bien ce type de programmation avec effet de bord puisque cette expression non seulement compare c EOF, mais encore le fait aprs avoir modi c. En liminant leffet de bord, on aurait pu crire la boucle while sous une forme plus habituelle pour un programmeur Pascal, mais certainement moins idiomatique pour un programmeur C :c = getchar(); while (c != EOF) { putchar(c); c = getchar(); }3. Contrairement C99 et C++, C90 ne possde pas de type de donne boolen mais que ce sont les valeurs entires 0 et 1 qui sont utilises pour jouer les rles respectifs de faux et vrai voir 3.3.2 et 11.3.2.

c Jean-Paul R IGAULT

V 2.1 7 fvrier 2010

2.3. Fonctions ; expressions ; entres-sorties

29

Notez la ncessit de rpter linstruction c = getchar(), une (lgre) nuisance. La fonction getchar lit le caractre suivant sur lentre standard et retourne sa valeur. En cas n de chier dtecte par le systme dexploitation, getchar retourne la valeur EOF, prdnie dans stdio.h et qui ne correspond aucune valeur possible de caractre 4 . La boucle while se terminera donc lorsque la n de chier sera atteinte sur lentre standard. Enn, le corps de la boucle est constitu par une instruction simple qui est linvocation de la fonction putchar. Celle-ci afche le caractre quelle reoit en argument (ici c) sur la sortie standard. Le programme, dont le source est dans le chier copy.c, peut donc servir recopier un chier dans un autre grce au mcanisme de redirection du shell :% make copy gcc -g -std=c99 -Wall % copy > fic ceci est le texte qui recopi sur la sortie D % cat fic ceci est le texte qui recopi sur la sortie % copy < fic > fic1 % cat fic1 ceci est un texte qui recopi sur la sortie % cmp fic fic1 %

-o copy copy.c sera standard

sera standard

sera standard

On rappelle que le caractre ctrl-d (eot) reprsent par D simule une n de chier au terminal. Par ailleurs, la commande cmp compare 2 chiers : labsence dafchage indique que les deux chiers sont identiques loctet prs.

2.3 Fonctions ; expressions ; entres-sorties2.3.1 Exemple : calcul de la racine carre dun relLe programme 2.4 calcule la racine carre dun nombre rel positif grce la mthode de Newton. Si t est un tel nombre, sa racine carre est en effet donne par la limite de la suite un = 1 2 u n 1 + t u n 1

avec la condition initiale u0 = t, par exemple. Le programme comporte, au plus haut niveau, sept lments. Trois directives au prprocesseur qui, comme prcdemment, permettent dimporter les prototypes des fonctions de la bibliothque standard :4. Ceci explique que getchar retourne un entier (int) et non pas un caractre (char) et que la variable locale c doive tre dclare comme un entier.

V 2.1 7 fvrier 2010

c Jean-Paul R IGAULT

30

2. Premiers pas

Programme 2.4 Calcul de la racine carre dun nombre rel/***** Fichier: square_root.c *****/ #include #include #include double square_root(double); int main() { double x; printf("entrez un nombre? "); scanf("%lg", &x); printf("resultat = %g\n", square_root(x)); exit(0); } const double EPS = 1.0e-06;20

5

10

15

/* precision maximale */

double square_root(double t) { double previous = 0.0; double current = t;25

30

35

if (t < 0.0) { fprintf(stderr, "argument negatif pour square_root\n"); exit(1); } while (fabs(previous - current) > EPS) { previous = current; current = 0.5 * (current + t / current); } return current; }

#include #include #include

Nous avons dj remarqu que linclusion de stdio.h permet dimporter les prototypes des fonctions dentre-sortie de la bibliothque standard ; celle de stdlib.h concerne une bonne partie du reste des prototypes de cette bibliothque (par exemple celui de la fonction exit) ; quant celle de math.h, elle importe les fonctions de la bibliothque mathmatique comme fabs. Un prototype dclarant la fonction square_root, car celle-ci est utilise avant dtre dnie (on parle de dclaration en avant (forward declaration) :

c Jean-Paul R IGAULT

V 2.1 7 fvrier 2010

2.3. Fonctions ; expressions ; entres-sorties

31

double square_root(double);

Cette fonction a un argument qui est un rel double prcision (type double) et retourne une valeur de mme type. La dnition de la constante globale EPS, galement de type double, initialise 106 . La dnition des deux fonctions main et square_root. On note que le format est libre et que lindentation et le changement de ligne sont largement utiliss pour rendre le programme lisible (ils nont pas dautre signication pour le compilateur que celle de sparateurs). La fonction main utilise une variable locale x, de type double. La valeur de x est lue grce la fonction de bibliothque scanf. Le premier argument de scanf est une chane de caractres qui spcie le format de lecture : ici, la spcication %lg signie quon cherche lire un rel dans toute prsentation raisonnable (le g), et que ce rel est double prcision (le l, comme long ). Le deuxime argument de scanf est ladresse de la variable que lon cherche lire, ici celle de x. En effet loprateur & sert prendre ladresse dun objet (il retourne un pointeur). De manire gnrale, les arguments de scanf doivent tre des pointeurs 5 . Lavant-dernire instruction de main afche le rsultat de linvocation de la fonction square_root avec largument x. L encore le premier argument de printf est un format o la spcication %g indique que lon veut afcher un rel double prcision dans un format raisonnable pour sa valeur. On constate au passage que printf et scanf sont des fonctions nombre variable darguments. Bien entendu, linvocation de exit termine lexcution du programme, en renvoyant au shell la valeur de son argument comme code de retour. Par convention, la valeur 0 indique que tout sest bien pass 6 . Il nest pas ncessaire dappeler systmatiquement exit la n de main, mais ce nest pas une mauvaise pratique puisque cela permet de matriser le code de retour transmis au shell. Une autre possibilit quivalente est de remplacer exit(code) par return code (par exemple ici, return 0) mais videmment ceci nest quivalent exit que pour le retour de main, pas dune autre fonction ! Notez aussi que le chier dentte dnit les deux constantes entires EXIT_SUCCESS (avec la valeur 0) et EXIT_FAILURE (1) ce qui permet de remplacer les utilisations de exit ou return prcdentes par exit(EXIT_SUCCESS) ou return EXIT_SUCCESS. Aprs la fonction main est dnie une constante globale EPS initialise la valeur 106 . Enn, on a dj remarqu que les commentaires se placent entre /* et */. Puis vient la dnition de la fonction square_root elle-mme. Elle vrie dabord que largument t nest pas ngatif. Linstruction if est lune des deux instructions de slection de C (voir 3.5.2). Elle peut prendre la forme simple suivante5. Essayez donc dexcuter ce programme en oubliant de prendre ladresse de x, cest--dire en crivant : texttscanf("%lg", x) 6. Rappelons que ce code de retour peut tre consult par les instructions de contrle conditionnelles du shell : if, while, until...

V 2.1 7 fvrier 2010

c Jean-Paul R IGAULT

32

2. Premiers pas

if (condition) instruction-si-vrai

ou encore celle dune alternativeif (condition) instruction-si-vrai else instruction-si-faux

Sa signication est vidente. Les deux instructions sont soit des instructions simples soit des blocs 7 . La fonction fprintf est analogue printf, mais son premier argument prcise le ux de sortie, ici lerreur standard stderr 8 . Le cur de square_root est un boucle while o current est la valeur courante de un et previous la valeur prcdente (i.e., un1 ). La fonction de bibliothque fabs calcule la valeur absolue relle double prcision (son prototype est dans math.h). La boucle sexcute tant que lcart en valeur absolue entre un et un1 est suprieur EPS. Le corps de la boucle tant constitu de deux instructions simples (deux instructions daffectation en fait), il faut donc l encore les englober dans un bloc. Lexpression arithmtique0.5 * (current + t / current)

se comprend sans problme. C dispose entrautres, des oprateurs arithmtiques habituels : addition (+), soustraction (-), multiplication (*), division (/). Ces oprateurs sappliquent des valeurs entires ou relles : attention, si ses deux oprandes sont entiers, / est la division entire. A la n de la boucle, la valeur de current est le rsultat cherch et est donc transmise lappelant grce linstruction return qui termine la fonction. Il ne reste plus qu compiler et excuter ce chier (supposons quil soit nomm square_root.c) :% make square_root gcc -g -std=c99 -Wall -o square_root square_root.c % square_root entrez un nombre? 64 result = 8 % square_root entrez un nombre? 2 result = 1.41421 % square_root entrez un nombre? 0 result = 0 % square_root entrez un nombre? 1.E+18 resultat = 1e+09 % square_root entrez un nombre? -12 argument negatif pour square_root %7. Remarquer labsence du mot-cl then habituel dans dautres langages. 8. printf(...) est donc quivalent fprintf(stdout, ...).

c Jean-Paul R IGAULT

V 2.1 7 fvrier 2010

2.3. Fonctions ; expressions ; entres-sorties

33

2.3.2 Entres-sorties formattesOn a vu que printf et scanf ont un premier argument 9 qui est un format prcisant les conversions effectuer en en sortie ou en entre. Nous donnons ici quelques indications pour permettre la comprhension des exemples venir. Pour les dtails on se reportera la documentation en ligne. Le format est une chane de caractres comportant des spcications de conversion , chacune dbutant par le caractre %. Une telle spcication indique la conversion effectuer sur largument correspondant (rappelons que les deux fonctions ont un nombre variable darguments). La correspondance entre spcication et argument seffectue donc de manire positionnelle et il doit en principe y avoir autant darguments convertir que de spcications dans le format.Conversions en sortie

Dans le cas de printf (ou de fprintf), tout ce qui nest pas une spcication de conversion est imprim tel quel. Ainsiprintf("hello, world!\n");

est un exemple o il ny a aucune spcication de conversion dans le format. Dansint i = 3; int j = 4; ... printf("i = %d, j = %d\n", i, j);

les valeurs de i et j sont imprimes en format dcimal (%d) produisanti = 3, j = 4

suivi dune n de ligne. Il existe un grand nombre de possibilits de spcications de conversion; voici quelques unes des plus frquentes :%d %o %x %c %s %lf %le %lg %% conversion dun entier en dcimal conversion dun entier en octal conversion dun entier en hexadcimal afchage dun caractre individuel afchage dune chaine de caractres conversion dun rel double en format xe conversion dun rel double en format avec exposant conversion dun rel double en format gnral le caractre % lui-mme

Le format, comme toute chane, peut contenir des squences dchappement qui reprsentent certains caractres non imprimables. Ces squences se composent toutes du caractre \ suivi dun seul caractre. Nous avons dj rencontr \n, voici les plus frquentes :9. La discussion qui suit sapplique aussi au deuxime argument de fprintf ou de fscanf dont le premier argument dsigne le ux dentre-sortie.

V 2.1 7 fvrier 2010

c Jean-Paul R IGAULT

34

2. Premiers pas

\n \t \f \0

n de ligne tabulation horizontale (tab) saut de page (form feed) le caractre nul (nul)

Le caractre nul joue un rle fondamental comme terminateur de chane de caractres (voir 3.1.7). Ne pas confondre ce caractre nul avec la constante NULL dsignant le pointeur nul (voir 5.1.1).Conversions en entre

Nous avons dj vu que les arguments de scanf sont des pointeurs. Les formats et les spcications de conversion ont pratiquement la mme syntaxe que pour printf, tout au moins en premire approximation. Le texte autre que les spcications de conversion et les espaces doit tre prsent dans lentre effective. Les espaces eux ne servent que de sparateurs et pour le reste sont ignors (le blanc, \n, \t, \f sont des espaces). Lexcution de scanf se termine lorsque toutes les spcications de conversion ont t satisfaites ; elle est abandonne prmaturment ds quune conversion ne peut tre effectue. Dans tous les cas, la valeur de retour est le nombre de conversions effectivement ralises. A titre dexemple, considrons le programme 2.5 (chier scanf.c) qui lit un entier (i) et un rel (x) et les afche avec le nombre dobjets lus (n). Programme 2.5 Programme simple de lecture de scalaires/***** Fichier: scanf.c *****/ #include 5

int main() { int i; double x; int n; n = scanf("%d toto %lg", &i, &x); printf("n = %d, i = %d, x = %lg\n", n, i, x); }

10

Voici quelques exemples de son excution :% make scanf gcc -g -std=c99 -Wall -o scanf scanf.c % scanf 12 toto 3 n = 2, i = 12, x = 3 % scanf 12 toto 3 n = 2, i = 12, x = 3 % scanf

c Jean-Paul R IGAULT

V 2.1 7 fvrier 2010

2.4. Tableaux et instruction ditration

35

12 toto 3 n = 2, i = 12, x = 3 % scanf 12toto3 n = 2, i = 12, x = 3 % scanf 12toto 3 n = 2, i = 12, x = 3 % scanf 12 3 n = 1, i = 12, x = 1.9064e-310 % scanf 12 to n = 1, i = 12, x = 1.9064e-310 % scanf aaaaaa 12 toto 3 n = 0, i = -1081747800, x = 1.9064e-310 %

Les valeurs tranges de x et i (en rouge) sont bien videmment le symptome que ces variables nont pas t initialises (dailleurs, on remarque que n est infrieur 2 dans ces cas). Les exemples prcdents montrent, sil en est besoin, que scanf est une fonction extrmement dlicate manipuler! lavenir, nous lviterons le plus possible!

2.4 Tableaux et instruction ditrationComme troisime exemple, le programme 2.6 ralise le tri par insertion dun tableau dentiers. Cet algorithme de tri seffectue sur place (cest--dire ne ncessite aucune mmoire supplmentaire) et requiert de lordre de n2 comparaisons (O(n2 )) si n est le nombre dlments trier 10 . Cette mthode est celle quutilise naturellement quelquun qui range ses cartes (au bridge ou au poker par exemple). La gure 2.1 schmatise un pas ditration de la boucle principale. On parcourt la liste de gauche droite, et on insre llment courant (dindice i) sa place dans la sous-liste de gauche (dj trie, par construction). Au besoin, pour ce faire, on cre un espace en dcalant des lments vers la droite. On trouve, au niveau principal, cinq lments dans ce programme : deux directives #include pour le prprocesseur ; la dnition de la fonction insertion_sort ; une directive au prprocesseur qui dnit la constante NMAX gale 1000#define NMAX 1000

la dnition de la fonction main. La fonction insertion_sort ralise lagorithme dcrit prcdemment. Si le nombre dlments trier n vaut 1 (ou moins) il ny rien faire. Linstruction return termine alors lexcution de la fonction. Cette instruction peut10. Les meilleurs algorithmes de tri squentiels sont en O(n log n) comparaisons.

V 2.1 7 fvrier 2010

c Jean-Paul R IGAULT

36

2. Premiers pas

Programme 2.6 Tri par insertion dune suite dentiers/***** Fichier: insertion_sort.c *****/ #include #include 5

void insertion_sort(int tab[], int n) { int i, j, current;10

15

20

if (n = 0; j--) { if (tab[j] = 0 && tab[j] > current; j--) { tab[j + 1] = tab[j]; } Par ailleurs, le corps de la boucle ne comportant quune seule instruction, les accolades sont inutiles : for (j = i - 1; j >= 0 && tab[j] > current; j--) tab[j + 1] = tab[j]; C possde aussi loprateur ou logique reprsent par ||. Ces deux oprateurs (|| et &&) sont valus de gauche droite, et lvaluation sinterrompt ds que le rsultat est dtermin. La fonction main dnit un tableau local t de dimension maximale NMAX. Ce tableau est initialis composante par composante grce scanf. On remarque que le corps de la boucle est vide, tout le travail ayant t fait par effet de bord dans la condition dentretien. A la n de la boucle, n est le nombre dlments lus. La liste trie par invocation de insertion_sort est imprime lment par lment grce printf. On noublie pas dajouter une n de ligne la n de la liste. Noter la diffrence entre les chanes de caractres littrales (entre ") et les caractres littraux (entre ).

Voici un exemple dexcution :% make insertion_sort gcc -g -std=c99 -Wall -o insertion_sort insertion_sort.c % insertion_sort entrez une liste dentiers termine par EOF? 12 -3 2 -1 7 -13 18 12 -27 D liste triee = -27 -13 -3 -1 2 7 12 12 18 %

2.5 Arguments du shell ; fonction rcursiveLe terme de rang n de la suite de Fibonacci est dni ainsi : u n = u n 1 + u n 2 u =0 0 u1 = 1 c Jean-Paul R IGAULTV 2.1 7 fvrier 2010

2.5. Arguments du shell ; fonction rcursive

39

Le programme 2.7 calcule un . La fonction fibo est une implmentation directe de la formule prcdente. Elle sinvoque rcursivement. La rcursion se termine car n dcroit chaque appel et nit donc par tre infrieur 2. Programme 2.7 Calcul du terme de rang n de la suite de Fibonacci/***** Fichier: fibo.c *****/ #include #include 5

10

int fibo(int n) { if (n < 2) return n; else return fibo(n-1) + fibo(n-2); } int main(int argc, char *argv[]) { int i; if (argc == 2) { i = atoi(argv[1]); } else { fprintf(stderr, "usage: fibo n\n"); exit(1); } printf("fibo(%d) = %d\n", i, fibo(i)); exit(0); }

15

20

25

La valeur de n est obtenue grce aux arguments de la ligne de commande qui correspondent aux arguments de la fonction main. On sait que sous le shell une commande est invoque par son nom avec une ventuelle liste darguments qui sont des chanes de caractres, comme dans% ls -lg -t -d /usr/bin /usr/local/bin

A lexcution de la commande correspond celle dun programme et donc dune fonction main si ce programme a t crit en C. Les arguments de main permettent de rcuprer les arguments positionnels de la commande shell : lentier argc est le nombre darguments positionnels y compris le nom de la commande (dans lexemple de ls, argc vaut 6) ; le tableau de chanes de caractres argv, dont la dclaration sera explicite en 5.3.2, contient lui les arguments positionnels, cest-dire ici les six chanes "ls", "-lg", "-t", "-d", "/usr/bin" et "/usr/local/bin".

V 2.1 7 fvrier 2010

c Jean-Paul R IGAULT

40

2. Premiers pas

La fonction de bibliothque standard atoi 11 transforme une chane de caractres (ici le premier argument positionnel de la commande, soit argv[1]) en entier, si toutefois cela a un sens. La fonction fibo aurait pu tre crite de manire plus idiomatique en utilisant une expression conditionnelle :int fibo(int n) { return (n < 2) ? n : fibo(n-1) + fibo(n-2);\\ }

Une expression commea ? b : c

se lit: si a alors b sinon c . Elle svalue comme cette lecture le laisse supposer. Voici un exemple dutilisation :% make fibo gcc -g -std=c99 -Wall -o fibo fibo.c % fibo 20 fibo(20) = 6765 % fibo 25 fibo(25) = 75025 % fibo 1 fibo(1) = 1 %

Une modication lmentaire de la fonction fibo permet de voir la rcursivit luvre (chier fibo1.c) :int fibo(int n) { int r; printf("entre dans fibo --- n = %d\n", n); if (n < 2) r = n; else r = fibo(n-1) + fibo(n-2); printf("sort de fibo --- n = %d, fibo = %d\n", n, r); return r; }

Voici le rsultat :% fibo1 4 entre dans fibo -entre dans fibo -entre dans fibo -entre dans fibo -sortie de fibo -- n entre dans fibo -sortie de fibo -- n11. pour ASCII to integer

n n n n = n =

= 4 = 3 = 2 = 1 1, fibo = 1 = 0 0, fibo = 0

c Jean-Paul R IGAULT

V 2.1 7 fvrier 2010

2.6. Exercices du chapitre 2

41

sortie de fibo -- n entre dans fibo -sortie de fibo -- n sortie de fibo -- n entre dans fibo -entre dans fibo -sortie de fibo -- n entre dans fibo -sortie de fibo -- n sortie de fibo -- n sortie de fibo -- n fibo(4) = 3 %

= n = = n n = n = = =

2, fibo = 1 1, fibo 3, fibo = 2 = 1 1, fibo = 0 0, fibo 2, fibo 4, fibo

= 1 = 1 = 2

= 1 = 0 = 1 = 3

Figure 2.2 Arbre de calcul rcursif de fibo(4)

On peut reprsenter ce calcul rcursif sous forme dun arbre comme dans la gure 2.2. La fonction fibo value cet arbre de la gauche vers la droite, en profondeur dabord , cest -dire en valuant effectivement les feuilles (indiques en bleu) dabord.

2.6 Exercices du chapitre 2Exercice 2.1 (Mise en route) Utiliser votre diteur favori pour saisir le texte de

lun des exemples de ce chapitre. Compiler et excuter cet exemple. Noter la coloration syntaxique (syntax highlighting) utilise par votre diteur (la plupart des diteurs actuels en disposent). Si votre diteur le permet ou si vous utilisez un environnement intgr comme kdevelop, eclipse, visual studio ou dev-c++, habituez-vous compiler et corriger vos erreurs sans quitter cet diteur ou cet environnement : cela fait gagner beaucoup de temps et vite les manipulations stupides 12 !Exercice 2.2 (Copie de chiers) Modier copy (programme 2.3) pour quil im-

prime le nombre de lignes copies sur lerreur standard (stderr).12. comme par exemple modier un chier et le compiler sans lavoir sauvegard au pralable. . .

V 2.1 7 fvrier 2010

c Jean-Paul R IGAULT

42

2. Premiers pas

Exercice 2.3 (La commande iota) crire le programme iota qui, lorsquil est invoqu depuis le shell avec largument n produit la suite des entiers de 1 n ;

par exemple

% iota 7 1 2 3 4 5 6 7 %

Exercice 2.4 (Minimum et maximum dun ensemble dentiers) crire un prog-

ramme qui imprime le maximum et le minimum dune liste dentiers.Exercice 2.5 (Conversion C ELSIUS -FARENHEIT) crire un programme qui im-

prime la table de conversion des degrs Celsius en degrs Farentheit entre -50C et +110C par pas de 5C , ainsi que la table inverse de -60F +220 F par pas de 10F. On rappelle la formule de conversion : si C est la temprature en C et F celle en F, on a F= 9 C + 32 5

Exercice 2.6 ( Drcursiver le calcul de la suite de F IBONACCI) Drcursi-

ver fibo, cest--dire remplacer les appels rcursifs par des boucles.Exercice 2.7 (Amlioration du calcul de la racine carre) Considrez le pro-

gramme de calcul de la racine carre par la mthode de Newton (programme 2.4). Excutez-le pour de petites valeurs de x, par exemple de lordre de 106 . Que se passe-t-il ? Identiez le problme. Quelle solution peut-on trouver pour amliorer la situation ? Vriez le rsultat.Suggestion

Si un est la suite utilise dans la mthode de Newton, que vaut la limite suivante ?n

lim

u n +1 un

Exercice 2.8 (Mauvais format) crire un programme qui utilise printf pour

imprimer un rel (float ou double) en format %d, un entier (int) en format %f et un caractre (char) en format %d. Faites le mme exercice mais en lecture, avec scanf. Que concluez-vous ?Remarque

Pour cet exercice, ignorez les messages davertissement (warnings) ventuels du compilateur. Pouvez-vous imaginer un moyen de faire taire ces messages ?

c Jean-Paul R IGAULT

V 2.1 7 fvrier 2010

Chapitre 3

Bases du langagedcrit du langage lexiOnscalaires, ici les lments fondamentaux instructions. C. .),: lments doncaux (identicateurs, sparateurs, constantes diverses. types de nes oprateurs et expressions, enn

3.1 Elments lexicaux3.1.1 Jeu de caractresLcriture dun programme C utilise un jeu de caractres qui doit au minimum comporter les lments suivants : lettres minuscules et majuscules, caractres spciaux (ponctuations, parenthses...), espaces (blanc, n de ligne, tabulations...). Les majuscules et les minuscules sont considres comme des caractres diffrents (en anglais, on parle de case-sensitivity). Le jeu de caractres le plus utilis est lascii dont la table 3.1 donne la description. Certaines machines relevant en particulier de la mouvance des gros ordinateurs ibm utilisent le code ebcdic qui contient les caractres imprimables du code ascii plus quelques autres. Dans le code ascii, les 32 premiers caractres (de nul us) ainsi que del sont non imprimables. La table 3.1 permet de trouver le code numrique correspondant un caractre : par exemple, le caractre A a pour code hexadcimal 41, soit 65 en dcimal ou encore 101 en octal. En fait la norme ansi C suppose que tous les caractres du code ascii sont reprsentables dans le jeu courant 1 , sauf @ et (la backquote).Portabilit du jeu de caractres

Il importe de remarquer que tout programme C qui fait une hypothse implicite sur le jeu de caractres utilis est par essence non portable. Un programme qui nutilise que le code ascii est en principe sr. Les codes dans lesquels un caractre est cod sur 8 bits peuvent galement tre manipuls sans trop de problme dans les chanes de caractres et seront rendus correctement si votre environnment est adquat (variables LANG par exemple). Ds que lon veut utiliser des jeux de caractres multi-octets comme Unicode, il vaut mieux se mettre en mode C99. Les fonctions correspondantes sont dcrites en 11.3.5.1. mais pas ncessairement dans le codage ascii!

C99

V 2.1 7 fvrier 2010

43

c Jean-Paul R IGAULT

44

3. Bases du langage

Table 3.1 Jeu de caractres ASCII 0 1 2 3 4 5 6 7 8 9 A B C D E F 0 nul soh stx etx eot enq ack bel bs tab nl vt ff cr so si 1 dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us 2 sp ! " # $ % & ( ) * + , . / 3 0 1 2 3 4 5 6 7 8 9 : ; < = > ? 4 @ A B C D E F G H I J K L M N O 5 P Q R S T U V W X Y Z [ \ ] ^ _ 6 a b c d e f g h i j k l m n o 7 p q r s t u v w x y z { | } ~ del

Remarque sur les digraphs et les trigraphs

C99

Au cas o le jeu de caractres disponible serait insufsant (!), la norme ansi C dnit une reprsentation particulire de certains caractres spciaux, dnomme trigraph . Les trigraphs comportent 3 caractres (!) dont les deux premiers sont ?? et sont remplacs par leur caractre quivalent dans tout contexte (y compris les chanes de caractres et les constantes litrales). On se porte aussi bien en ignorant cette bizarrerie 2 mais il convient dviter le double point dintrrogation en particulier dans les commaentaires (voir 3.1.3) et constantes littrales reprsentant des caractres individuels (voir3.1.6) ou des chanes (voir 3.1.7) ! Ajoutant le saugrenu la bizarrerie, C++a aussi dni des squences de deux caractres (donc des digraphs ) permettant de reprsenter aussi une partie de caractres spciaux. C99 sest prcipit pour adopter cette ide gniale. Ainsi les crochets carrs ([ et ]) peuvent-ils tre reprsents par , les accolades ({ et }) par , le dise (#) par %: et le double dise (##) videmment par %:%:. Cela namliore certes pas la lisibilit ! Contraitrement aux trigraphs, les digraphs ne sont pas substitus lintrieur dun commentaire ni dune constante littrale (chane ou caractre) ; en fait leur substitution na lieu que sils reprsentent par euxmmes un lment lexical (un token voir 3.1.2). Il est peu probable que vous ayez utiliser les digraphs...

3.1.2 Structure lexicale dun chier-sourceUn chier de source C est constitu dlments lexicaux qui se divisent en six catgories : mots-cls, identicateurs, constantes arithmtiques littrales, chanes de caractres littrales, oprateurs et autres sparateurs.2. Cette bizarrerie a une raison, cependant. Les caractres correspondants sont ceux utiliss par C++ qui sont absents du jeu de caractres normalis suppos tre implant sur toutes les machines, lInvariant Code Set iso 646-1983.

c Jean-Paul R IGAULT

V 2.1 7 fvrier 2010

3.1. Elments lexicaux

45

Les sparateurs permettent disoler les autres lments lexicaux. Les oprateurs sont aussi des sparateurs. Les espaces, cest--dire le blanc (sp), la n de ligne (nl), les tabulations horizontale (tab ou ht) ou verticale (vt) et le saut de page (ff) sont des sparateurs purs en ce sens que pour le reste ils sont ignors.

3.1.3 CommentairesEn C90 les commentaires sont encadrs entre /* et */ et peuvent stendre sur plusieurs lignes mais ne peuvent pas simbriquer :/* Un long commentaire sur 3 lignes */ /* Une /* erreur de syntaxe */ coup sr ! */

Ce type de commentaire est quivalent un espace pour le compilateur (cest donc un sparateur). C99 autorise aussi les commentaires la C++ commenant par // et stendant jusqu la n de la ligne. Il est possible dimbriquer un commentaire C90 dans un commentaire C99 ou linverse :// un commentaire-ligne /* Toute une section en commentaire, y compris ses commentaires-lignes x = 0; // plus de x y = 1; // encore un y / *

C99

3.1.4 IdenticateursLes identicateurs permettent de nommer des objets (constantes, variables, fonctions). Ils commencent par une lettre ou le caractre soulign (_) suivi dune squence de lettres, de chiffres ou de souligns. Par exemple :x j21 Prix_HT _strcmp X a2ps Square_Root __DATE__ toto char_0_to_9 num_secu __STDC__ NBUF PascalStyleId _1993

En revanche, les mots suivants ne sont pas des identicateurs :#x 2#$!**)((_+%^ 2toto Prix-TTC

On rappelle que les majuscules et les minuscules sont considres comme des caractres diffrents : Square_Root et square_root ne sont pas le mme identicateur.Portabilit : jeu de caractres tendu pour les identicateurs

En C90, seul le code ascii peut tre utilis pour coder les identicateurs (noms de constantes, variables, fonctions, macros. . .). En revanche, C99 permet lutilisation des caractres tendus (Unicode)

C99

V 2.1 7 fvrier 2010

c Jean-Paul R IGAULT

46

3. Bases du langage

dans les identicateurs. Cependant, peu de compilateurs ralisent actuellement cette fonctionalit (en particulier gcc-4.2 ne la supporte pas). On vitera donc les identifcateurs comme t42 ou .Portabilit : identicateurs rservs

Les identicateurs dbutant par un double caractre soulign (_) sont rservs des usages spciaux (voir 6.3.6) et ne devraient pas tre utiliss en dehors de ces usages. En principe, les noms de fonctions de la bibliothque normalise (fopen, printf, exit... voir 9) ne devraient pas tre utiliss pour dautres usages. Enn, les mots-cls (voir 3.1.5) sont strictement rservs.Portabilit : longueur dun identicateur

La norme ansi C rclame que les 31 premiers caractres au moins dun identicateur soient pris en compte sauf pour les identicateurs dobjets externes qui sont manipuls par lditeur de liens. Pour ces derniers, les 6 premiers caractres au moins doivent tre signicatifs. Les compilateurs et les diteurs de liens modernes ne placent pratiquement aucune limite sur la longueur des identicateurs. Se mer cependant : quant la modernit, les diteurs de liens sont bien plus rares que les compilateurs !

3.1.5 Mots-clsLes mots-cls de C sont strictement rservs. Ils ne doivent pas tre utiliss comme identicateurs sinon le programme devient incompilable. Tous les mots-cls sont en minuscules ; ils sont au nombre de 32 pour C90 et le tableau 3.2 en donne la liste. Table 3.2 Mots-cls de C 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

C99

La norme C99 ajoute 5 mots-cls supplmentaires (table 3.3). Table 3.3 Mots-cls supplmentaires de Cnew restrict inline _Complex _Imaginary _Bool

3.1.6 Constantes littrales arithmtiques

c Jean-Paul R IGAULT

V 2.1 7 fvrier 2010

3.1. Elments lexicaux

47

Constantes littrales caractres

La squence a reprsente le caractre a. Une constante caractre est donc un caractre encadr de simples quotes (). Lorsque le caractre nest pas imprimable, on peut utiliser une squence dchappement comme \n. La table 3.4 donne la liste complte de ces squences. Table 3.4 Squences dchappement pour les caractres

\a \b \f \n \r \t \v \\ \0 \ \" \?

alarme retour arrire saut de page saut de ligne retour chariot tabulation horizontale tabulation verticale le \ lui-mme le caractre de code 0 la simple quote elle-mme la double quote elle-mme le point dinterrogation

alarm backspace form feed new line carriage return horizontal tab vertical tab backslash nul

bel bs ff nl cr tab (ht) vt nul

A titre dexemple, le programme 3.1 remplace chaque n de ligne de lentre standard par un blanc. Programme 3.1 Remplacement des ns de ligne par un blanc/***** Fichier: rm_nl.c *****/ #include 5

int main() { int c; while ((c = getchar()) != EOF) { if (c == \n) c = ; putchar(c); } putchar(\n); }

10

15

Portabilit : valeur entire dun caractre

La norme permet de reprsenter tout caractre par son code octal ou hexadcimal. Ainsi A, \101 et \x41 sont trois reprsentations quivalentes de la constante caractre A. Conformment la remarque dj faite en 3.1.1, ceci peut tre une cause de non-portabilit.

V 2.1 7 fvrier 2010

c Jean-Paul R IGAULT

48

3. Bases du langage

Constantes entires littrales

ansi C supporte trois reprsentations principales des constantes entires littrales : dcimale, constitue des chiffres de 0 9 (0, 123, 2812727837...) ; octale, dbutant par le caractre 0 et ne comportant que les chiffres de 0 7 (0123, 0177) ; hexadcimale, dbutant par le prxe 0x ou 0X et constitue des chiffres de 0 9 et des lettres de a f en majucules ou minuscules indiffremment (0x10 , 0xff, 0XaaBBcc00...). Une constante entire littrale peut tre prcde dun signe (+ ou -). Ce signe ne fait pas rellement partie de la constante mais dsigne en fait loprateur correspondant (voir 3.3.1). Il existe de nombreuses variations de syntaxe des constantes entires qui correspondent aux diffrents sous-types des entiers et qui seront tudies en 3.2.3.Constantes relles littrales

Les constantes relles littrales peuvent prendre deux formes : virgule xe avec une partie entire et une partie fractionnaire (dcimales) spares par un point (2.718285, 0.314159...) ; exponentielle, identique la virgule xe avec en plus un facteur dchelle introduit par le caractre e ou E et qui reprsente un exposant en base 10 (6.02e+23 pour 6, 02 1023 , 1.e-6 pour 106 ...). Les deux remarques prcdentes sur la prsence possible dun signe et lexistence de variations sappliquent ici aussi (voir 3.2.4 pour les variations).

3.1.7 Chanes de caractres littralesUne chane de caractres littrale est une suite de caractres encadres de doubles quotes . Les squences dchappement (3.1.6 et table 3.4) sont bien entendu utilisables :"ceci est une chaine de caracteres litterale" "hello, world\n" "Article\tPrix unitaire\tQuantite\tPrix total" "la double quote comme \" cad avec un \ devant"

Une chane de caractres littrale ne peut tre coupe par un retour la ligne : ceciprintf("hello, world \n");

est illgal. Cependant quand des chanes littrales sont adjacentes (cest--dire uniquement spares par des espaces), elles sont concatnes par le compilateur :printf("hello, " "world" "\n");

est quivalent printf("hello, world\n");

c Jean-Paul R IGAULT

V 2.1 7 fvrier 2010

3.1. Elments lexicaux

49

Figure 3.1 Reprsentation dune chane de caractres littrale

En mmoire, une chane littrale est reprsente par la suite des caractres qui la constitue (sans les doubles quotes bien sr) termine par le caractre nul (\0). Ainsi, une chane occupe-t-elle un caractre de plus que sa longueur utile (gure 3.1). Cette proprit, qui est impose par le compilateur pour les chanes littrales, est une convention qui doit tre respecte par le programmeur en manipulant des chanes variables. A titre dexemple, les deux programmes 3.2 et 3.3 utilisent cette proprit de terminaison des chanes : le premier pour dterminer la longueur utile, le second pour recopier une chane dans une autre noter que le caractre nul nal est lui aussi recopi. Programme 3.2 Longueur utile dune chane de caractres/***** Fichier: string_length.c *****/ #include 5

int string_length(const char orig[]) { int i; for (i = 0; orig[i] != \0; i++) {} return i; } int main() { printf("%d\n", string_length("hello, world\n")); }

10

15

Pour ces deux programmes, on remarque que largument orig est pass sous forme dun tableau de caractres constantsconst char orig[]

ce qui signie que les lments du tableau ne sont pas modis dans le corps de la fonction (voir 7.3.2). En revanche, le tableau dest, paramtre de copy_string, est videmment modiable, dou labsence de const. Noter aussi le corps vide de la boucle de la fonction string_length : tout le travail est en effet ralis dans lentte de linstruction for.Attention : a et "a"

On ne doit donc pas confondre la constante charactre a avec la chane

V 2.1 7 fvrier 2010

c Jean-Paul R IGAULT

50

3. Bases du langage

Programme 3.3 Copie de chanes de caractres/***** Fichier: copy_string.c *****/ #include 5

void copy_string(char dest[], const char orig[]) { int i; for (i = 0; orig[i] != \0; i++) dest[i] = orig[i]; dest[i] = \0; /* copie du nul terminal */ } int main() { char str[100]; copy_string(str, "hello, world\n"); printf(str);

10

15

20

}

de caractres "a" rduite a et dont la reprsentation en mmoire comporte en fait deux caractres (a et \0).

3.2 Types scalaires et dclarations simples3.2.1 Panorama des types de CIl y a deux manires de classier les types de donnes en C : les types scalaires dune part et les agrgats dautre part ; les types de base dune part et les types utilisateurs dautre part. Le tableau 3.5 schmatise cette situation. Comme son titre lindique, cette section ne concerne que les types de base. Les agrgats et les pointeurs sont respectivement tudis aux chapitres 4 et 5.

3.2.2 Type vide (void)Le type void (qui ne gure pas dans le tableau 3.5) joue un rle particulier en ce sens quil ny a aucun objet de ce type il dsigne en quelque sorte lensemble vide. A quoi peut-il servir? En fait, il nest utilis que dans trois circonstances qui seront tudies plus tard : pour dclarer quune fonction na pas darguments (7.2.1) ; pour dclarer quune fonction na pas de rsultat cest une procdure (7.2.1) ; enn, dans le sens conventionnel de pointeur sur void (void* 5.1.4).

c Jean-Paul R IGAULT

V 2.1 7 fvrier 2010

3.2. Types scalaires et dclarations simples

51

Table 3.5 Panorama des types de CTypes scalaires entiers Types de base char avec variations de signe (signed et unsigned), int avec variations de longueur (short, long) et de signe (signed et unsigned) float, double, long double tableaux, structures (struct), unions (union) Types utilisateurs pointeurs, numrations (enum)

Types scalaires rels Agrgats

3.2.3 Types de base entiersC possde une grande varit de types de nature entire (integral types). Comme indiqu dans le tableau 3.5 cela inclut bien entendu la reprs