Vous êtes sur la page 1sur 238

Support de Cours de Langage C

Christian Bac 24 avril 2003

ii

c Christian Bac 1985-2003

Table des matires


Avant-propos 1 Historique et prsentation
1.1 1.2 1.3 1.4 Historique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Prsentation du langage Ides fondamentales En-chaneur de passes 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 Pr-processeur Compilateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

xi 1
1 2 3 5 7 7 7 7 7 8

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

Optimiseur de code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Assembleur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

diteur de liens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Quelques options de cc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2 Gnralits sur la syntaxe


2.1 Mise en page 2.1.1 2.1.2 2.2 2.3 2.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Identiant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Espaces lexicaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9
9 9 9 10 10 10

Mots rservs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Instructions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3 Types et variables
3.1 Types de base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1.1 3.1.2 3.1.3 3.2 Types entiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Types avec parties dcimales Tailles des types . . . . . . . . . . . . . . . . . . . . . . . . . .

11
11 12 12 12 13 13 14 14

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

Constantes associes aux types de base . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.1 3.2.2 3.2.3 Constantes de type entier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Constantes avec partie dcimale Constantes de type caractre

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

c Christian Bac 1985-2003

iv

TABLE DES MATIRES

3.2.4 3.3 3.4 3.5 3.6

Chanes de caractres

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

15 15 15 16 18 18 19 20 21 22 23 23 23 23 24 25

Qualicatifs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Taille et normalisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dnition de variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Types drivs des types de base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.6.1 3.6.2 Tableaux et structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pointeurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3.7 3.8

Initialisation de variables

Conversion de type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.8.1 Conversions implicites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3.9

Dclaration et dnition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3.10 Exercices sur les types et variables

3.10.1 Exercice 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.10.2 Exercice 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.10.3 Exercice 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.10.4 Exercice 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4 Elments de base
4.1 4.2 4.3 4.4 4.5 Bonjour . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Lire et crire

27
27 28 29 29 31 31 31 31 32

Quelques oprations Plus sur

printf()

et

scanf() .
et

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

Exercices sur 4.5.1 4.5.2 4.5.3 4.5.4

printf()

scanf()

Exercice 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercice 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercice 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercice 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5 Oprateurs et expressions
5.1 Oprateurs un-aires 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.1.8 5.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Oprateur de rfrencement . . . . . . . . . . . . . . . . . . . . . . . . . . . Oprateur de drfrencement ou indirection Utilisation des & et * . . . . . . . . . . . . . . . . .

37
37 38 38 38 39 40 40 40 40 41 41

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

Oprateurs d'incrmentation et de dcrmentation

Oprateur de taille . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Oprateur de ngation logique Plus et moins unaires Complment un . . . . . . . . . . . . . . . . . . . . . . . . .

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

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

Oprateurs binaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.2.1 Oprateurs arithmtiques . . . . . . . . . . . . . . . . . . . . . . . . . . . .

c Christian Bac 1985-2003

TABLE DES MATIRES

5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7 5.2.8 5.3 5.4 5.5

Oprateurs manipulant les bits Oprateurs de dcalage

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

41 42 43 44 44 45 46 47 47 48 48 48 48 48 49 49

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

Oprateurs de relation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Oprateur binaire d'aectation et de succession . . . . . . . . . . . . . . . . Oprateurs d'aectation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Oprateur ternaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Prcdence des oprateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Expressions

Instructions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercices sur les oprateurs et les expressions . . . . . . . . . . . . . . . . . . . . . 5.5.1 5.5.2 5.5.3 5.5.4 5.5.5 5.5.6 Exercice 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercice 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercice 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercice 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercice 5 : Operateur ternaire . . . . . . . . . . . . . . . . . . . . . . . . . Exercice 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6 Instructions de contrle
6.1 Instructions conditionnelles 6.1.1 6.1.2 6.2 Test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

57
57 57 58 60 60 61 62 63 63 63 63 65 65 66 66 66 66 66 66 66 66

Table de branchement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Instructions itratives 6.2.1 6.2.2 6.2.3 6.2.4

while for

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

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

do while

Remarques sur les instructions itratives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6.3

Ruptures de squence 6.3.1 6.3.2 6.3.3 6.3.4

continue break
goto

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

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

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

return

6.4

Exercices sur les instructions de contrle . . . . . . . . . . . . . . . . . . . . . . . . 6.4.1 6.4.2 6.4.3 6.4.4 Exercice 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercice 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercice 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercice 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6.5

Exercices sur les ruptures de squence 6.5.1 6.5.2

Exercice 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exercice 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . c Christian Bac 1985-2003

vi

TABLE DES MATIRES

7 Programmation structure
7.1 7.2 7.3 Historique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ides fondamentales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

83
83 83 84 84 84 84 85 86

Langage C et programmation structure . . . . . . . . . . . . . . . . . . . . . . . . 7.3.1 7.3.2 Ambitions du langage C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C et structures fondamentales . . . . . . . . . . . . . . . . . . . . . . . . . .

7.4

Quelques exemples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.4.1 7.4.2 Exemple avec des tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exemple avec une boucle . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8 Fonctions
8.1 8.2 8.3 Dnition d'une fonction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Retour de fonction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

95
95 96 97 97 99 99 102 102 103 103 103 106 106 106 106

Passage des paramtres 8.3.1 8.3.2

Passage de constantes Passage de variables

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

8.4 8.5 8.6 8.7 8.8 8.9

Utilisation de pointeurs en paramtres . . . . . . . . . . . . . . . . . . . . . . . . . Conversion de type lors des appels Rcursivit . . . . . . . . . . . . . . . . . . . . . . . . . . .

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

Arguments de la fonction main() Pointeur de fonction

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

tapes d'un appel de fonction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8.10 Exercices sur les fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.10.1 Exercice 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.10.2 Exercice 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.10.3 Exercice 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9 Compilations spares
9.1 9.2 9.3 Programme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fichier source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Visibilit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.3.1 9.3.2 9.4 9.5 9.6 9.7 9.8 Espaces de nommage et visibilit . . . . . . . . . . . . . . . . . . . . . . . . Extension de la visibilit . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

111
111 111 113 114 114 115 116 116 116 117 118 119

Prototypes des fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fonctions externes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Fonctions dnies ultrieurement Vrication des prototypes

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

Multiples dclarations et dnitions 9.8.1 9.8.2

Fichiers d'inclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Rduction de la visibilit . . . . . . . . . . . . . . . . . . . . . . . . . . . .

c Christian Bac 1985-2003

TABLE DES MATIRES

vii

9.8.3 9.8.4 9.9

Variables locales rmanentes Travailler en groupe

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

119 120 121 121 121 121

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

Exercices sur les fonctions et la visibilit des variables 9.9.1 9.9.2 9.9.3

Exercice 1 : simulation d'un ascenseur . . . . . . . . . . . . . . . . . . . . . Exercice 2 : racines d'une quation du deuxime degr . . . . . . . . . . . . Exercice 3 : utilisation des chiers d'inclusion . . . . . . . . . . . . . . . . .

10 Pointeurs et tableaux
10.1 Tableaux une dimension . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.2 Arithmtique d'adresse et tableaux . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.3 Tableaux multidimensionnels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

129
129 130 131 132 133 135 135 135

10.4 Pointeurs et tableaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.5 Tableau de pointeurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.6 Pointeurs vers un tableau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10.7 Exercices sur les tableaux et les pointeurs

10.7.1 Exercice 1 : tri de tableaux d'entiers . . . . . . . . . . . . . . . . . . . . . .

11 Structures
11.1 Dnition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2 Utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2.1 Oprations sur les champs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2.2 Oprations sur la variable dans son ensemble 11.3 Structures et listes chanes . . . . . . . . . . . . . . . . .

143
143 144 144 144 145 145 146 146 147

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

11.4 Champs de bits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.5 Exercices sur les structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

11.5.1 Exercice 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.5.2 Exercice 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12 Unions
12.1 Dnition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.2 Accs aux champs

149
149 150 150 150 151

12.3 Exercices sur les unions et les champs de bits

12.3.1 Exercice 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.3.2 Exercice 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13 numrations
13.1 Dnition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.2 Utilisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.3 Limites des numrations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

153
153 154 155

14 Types synonymes et complexes


c Christian Bac 1985-2003

157

viii

TABLE DES MATIRES

14.1 Types synonymes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14.2 Types complexes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

157 158 158 160 160 161 161

14.3 Fonctions et tableaux

14.4 Exercices sur les dclarations complexes

14.4.1 Exercice 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14.4.2 Exercice 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14.4.3 Exercice 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15 Prprocesseur
15.1 Commentaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15.2 Inclusion de chiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15.3 Variables de pr-compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15.3.1 Dnition de constantes de compilation 15.3.2 Dnition destine la slection . . . . . . . . . . . . . . . . . . . .

165
165 165 168 168 168 168 169 169 170 171 171 171 171 171

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

15.4 Dnition de macro-expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15.5 Eacement d'une dnition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15.6 Dnition l'appel de l'enchaneur de passes

15.7 Slection de code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15.7.1 Slection avec 15.7.2 Slection avec

#if

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . et

#ifdef

#ifndef .

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

15.8 Exercices sur le prprocesseur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15.8.1 Exercice 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15.8.2 Exercice 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16 Entres-sorties de la bibliothque
16.1 Entre-sorties standards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.1.1 changes caractre par caractre . . . . . . . . . . . . . . . . . . . . . . . . 16.1.2 changes ligne par ligne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.1.3 changes avec formats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.2 Ouverture d'un chier 16.3 Fermeture d'un chier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

179
179 180 181 182 183 184 185 185 186 188 190 190 191 193 193

16.4 Accs au contenu du chier

16.4.1 Accs caractre par caractre

16.4.2 Accs ligne par ligne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.4.3 Accs enregistrement par enregistrement . . . . . . . . . . . . . . . . . . . . 16.5 Entre-sorties formates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16.5.1 Formats : cas de la lecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.5.2 Formats : cas de l'criture . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.5.3 Conversion sur les entre-sorties standards . . . . . . . . . . . . . . . . . . . 16.5.4 Conversion en mmoire . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

c Christian Bac 1985-2003

TABLE DES MATIRES

ix

16.5.5 Conversion dans les chiers 16.6 Dplacement dans le chier

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

193 194 196 197

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

16.7 Gestion des tampons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.8 Gestion des erreurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17 Autres fonctions de la bibliothque


17.1 Fonctions de manipulation de chanes de caractres . . . . . . . . . . . . . . . . . . 17.2 Types de caractres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

203
203 203 204 204 204

17.3 Quelques fonctions gnrales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17.3.1 17.3.2

system() exit()

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

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

GNU Free Documentation License


17.4 Applicability and Denitions 17.5 Verbatim Copying . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

207
207 208 208 209 210 210 211 211 211 211

17.6 Copying in Quantity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17.7 Modications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17.8 Combining Documents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17.9 Collections of Documents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17.10Aggregation With Independent Works 17.11Translation

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

17.12Termination . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17.13Future Revisions of This License . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Liste des programmes exemples Liste des gures Liste des tableaux Bibliographie Index

212 215 218 220 221

c Christian Bac 1985-2003

TABLE DES MATIRES

c Christian Bac 1985-2003

Avant-propos
Notice de copyright
NOTICE de COPYRIGHT c Ce support de cours correspond au cours de langage C de Christian Bac (ci-aprs l'auteur, je ou moi) de l'Institut National de Tlcommunications, 9 rue Charles Fourier 91011, vry, France.

http ://picolibre.int-evry.fr/projects/coursc/.

Ce document est disponible aux formats latex, PostScript ou HTML, sur le web l'URL :

Il est fourni tel quel, l'auteur ayant fait de son mieux pour supprimer les erreurs, sans garantie sur son utilisabilit, ni sur l'exactitude des informations qu'il contient. Vous avez le droit de copier, distribuer et/ou modier ce document selon les termes de la licence de documentation libre, version 1.1 ou toute version postrieure publie par la Free Software Foundation ; avec une section invariante le chapitre

Avant-propos qui contient cette licence, sans

texte spcique en premire et en quatrime de couverture. Une copie de la licence est inclue dans le chapitre 17.3.2 intitul "GNU Free Documentation License". Toute remarque ou erreur peut tre notie l'auteur l'adresse lectronique suivante :

Christian.Bac AT int-evry.fr
Fin de la NOTICE de COPYRIGHT c -

Conventions d'criture
Voici les conventions d'criture suivies dans ce support :  le  en anglais comme

style italique n'est quasiment jamais utilis car je ne l'aime pas, je le rserve pour les phrases The C programming Language et pour les locutions latines comme versus ; les caractres de type imprimante boule (teletype) sont utiliss pour les noms de chiers et les parties de programme, comme /usr/include/stdio.h ;

 le

 les caractres sont plus larges dans l'nonc de rgles ou de parties de syntaxe telles que la syntaxe de la conversion explicite : (type) expression ;  les mots qui ne sont pas franais mais sont souvent utiliss dans le jargon des informaticiens comme quote sont considrs comme de type neutre et se voient appliquer le genre masculin. Ainsi je peux appeler un index-noeud du systme de chiers UNIX : un inode ;  dans les dessins reprsentant l'espace mmoire occup par les variables ou les tableaux, les noms entours par des pointills sont des adresses et non des variables.

style gras est utilis lorsqu'un mot me semble important, par exemple instructions ;

c Christian Bac 1985-2003

xii

Vocabulaire courant
Voici quelques mots que j'utilise de manire courante :

Bit

(Binary digiT) ou lment binaire, la plus petite partie manipulable par un ordinateur. Comme son nom l'indique un lment binaire peut prendre deux valeurs : 0 ou 1.

Octet

ou

byte,

le groupe de bits qui permet de supporter la reprsentation d'un caractre. Ce

groupe est le plus souvent (comme son nom l'indique) constitu de huit bits. En langage C, l'octet sert dans les calculs d'occupation d'espace mmoire et en particulier les variables plus compliques comme le mot machine ont une taille donne en nombre d'octets.

Pile

ou pile d'excution, c'est une partie de l'espace mmoire d'une application qui permet au programme de tenir jour des sries de variables actives. Cet espace est gr comme une pile d'assiettes, c'est--dire que l'on peut ajouter de l'espace (faire grandir la pile) ou diminuer cet espace seulement par le haut. Ainsi, les derniers lments qui ont t ajouts sur une pile sont les plus facilement accessible, une pile reprsente le modle LIFO (Last

Out )

In First

les derniers lments qui y sont ajouts sont les premiers pouvoir tre retirs. Les

oprations d'agrandissement ou de rduction de la pile sont faites de manire automatique lors des appels de fonctions et respectivement des retours de fonctions. La pile est gre partir d'un espace mmoire de taille xe qui est attribu de manire automatique par le systme d'exploitation. Le processeur tient jour sa relation avec la pile travers un registre interne qui dcrit le sommet de pile et un autre registre qui maintient un lien sur le contexte (arguments de l'appel et variables locales).

Un peu d'histoire
Ce cours de langage C a la gnalogie suivante :

Gnse

1. Il a t cr en 1985 lorsque j'tais au centre de calcul du CNET Paris A, pour assurer la formation en interne.

2. La premire version tait tape avec les accents franais grce une version d'Emacs sur

Multics

amliore par M. Arditti. Cette version d'Emacs permettait de taper les

accents. 3. Les exercices associs ont t raliss sur une machine de type SM90. 4. Les personnes m'ayant aid dans la ralisation de cette premire version sont : M. Auguste et M. Sabatier du CNET.

Tro

1. Lorsque le

DWB (Documentation WorkBench) a t disponible suite une intense partroff.

ticipation du CNET travers la personne de M. Gien, dans l'organisation de la confrence Europenne sur UNIX Paris en 1986, j'ai dcid de faire migrer ce cours sous une version

2. J'ai alors choisi d'utiliser les macros qui me semblaient devoir tre la future rfrence car elles faisaient partie de la distribution d'UNIX que j'ai t le seul). 3. Les premires gures sont apparues dans ce support grce la disponibilit de l'utilitaire

system V,

les macros

-mm

(je crois

pic.

4. Les personnes m'ayant aid dans la ralisation de cette version sont : M. Fondain et M. Horn du CNET.

Utilisation en formation continue

Cette version m'a suivi lorsque j'ai quitt le CNET pour

venir travailler l'INT en 1989. Elle a alors servi de support de cours pour la mise en place d'un ensemble de cours dus l'arrive du systme UNIX dans les services oprationnels, par le service national de la formation de France Tlcom.

Macintosh

J'ai arrt de modier cette version en 1991, pour deux raisons : c Christian Bac 1985-2003

CHAPITRE 0.

AVANT-PROPOS

xiii

1. premirement, j'ai crit des addendas avec du langage.

Microsoft Word

pour

Macintosh.

Ces ad-

dendas avaient pour but d'expliquer les modications apportes par la normalisation

2. deuximement, j'ai constitu un jeu de transparents partir de ce cours en supprimant des phrases et en modiant les polices de caractres de manire le rendre lisible une fois projet. Ce jeu de transparents est devenu mon nouveau support de cours et je l'ai fait voluer de manire indpendante.

LaTeX

J'ai dcid en 1997 de reconstituer ce support en utilisant 1. pour moi, ce fut un trs bon apprentissage de

LaTeX,

avec plusieurs buts :

LaTeX et il constitue une sorte de rfrence

lorsque je veux rdiger un nouveau document ; 2. grce des outils comme

LaTeX2HTML,

je peux permettre aux autres de consulter ce

support sur le World Wide Web ; 3. j'ai mesur la limite des transparents surtout lorsqu'ils sont utiliss par les lves comme support de cours. Je tiens souligner la participation active de Mmes. Monget et Carpentier, Ms. Conan, Volt et Laleve dans la relecture et la correction de ce support. Je suis aussi redevable, ce dernier de moult conseils relatifs l'utilisation de

GnuFDL

LaTeX2e.

En 2003, je suis convaincu des vertus du partage au travers d'Internet, non seulement

des codes mais aussi du savoir, j'ai plac ce cours sous licence GNU Free Documentation Licence pour lui permettre de continuer vivre et pour faciliter son utilisation par mes collgues enseignants francophones. Pour l'occasion, j'en ai prott pour associer ce support quelques exercices et leurs corrigs qui taient sur un support spar. Je tiens enn remercier les internautes qui m'envoient des correctifs ou des remarques qui permettent ce cours de s'amliorer.

c Christian Bac 1985-2003

xiv

c Christian Bac 1985-2003

Chapitre 1

Historique et prsentation
Ce chapitre essaye de placer le langage C [BK78] dans son contexte historique et technique, de manire approcher l'tat d'esprit du langage qui nous permet de deviner les rgles sous-jacentes au langage sans pour cela avoir les mmoriser.

1.1 Historique
Le langage C [DR78] est li la conception du systme ayant inuenc son dveloppement sont :  le langage  le langage

UNIX1

par les Bell-Labs. Les langages

BCPL de M. Richards 1967 ; B dvelopp aux Bell-Labs 1970.

Ces deux langages partagent avec le langage C :  les structures de contrle ;  l'usage des pointeurs ;  la rcursivit. Ces deux langages prdcesseurs du C avaient la particularit d'tre sans type. Ils ne travaillaient que sur des donnes dcrites par un mot machine ce qui leur donnait un degr de portabilit nul. Le langage C comble ces lacunes en introduisant des types de donnes tels que l'entier, ou le caractre. Les dates marquantes de l'histoire du langage  1970 diusion de la famille PDP 11.  1971 dbut du travail sur le langage C, car le PDP 11 peut manipuler un octet alors que son mot mmoire est de 2 octets, il est ncessaire pour utiliser les fonctionnalits du PDP11 introduire un type de donne char et un type int. Ces notions de type n'tant pas prises en compte par le langage B, elles le seront dans son successeur le C.  1972 la premire version de C est crite en assembleur par Brian W. Kernighan et Dennis M. Ritchie.  1973 Alan Snyder crit un compilateur C portable (thse MIT).  1975 Steve C. Johnson crit et prsente le PCC (Portable C Compiler). C'tait l'poque le compilateur le plus rpandu. Le PCC a longtemps assur sa propre norme puisqu'il tait plus simple de porter le PCC que de rcrire un compilateur C (25 % du code du PCC modier).  1987 dbut de la normalisation du langage par l'IEEE avec constitution d'un comit appel : X3 J-11.

C sont les suivantes :

l'poque UNIX tait une marque dpose des laboratoires Bell. Aujourd'hui, c'est devenu un nom quasiment

commun :-), bien que la marque soit toujours la proprit de certication.

The Open Group qui pratique des programmes de

c Christian Bac 1985-2003

1.2.

PRSENTATION DU LANGAGE

 1989 sortie du premier document normalis appel norme ANSI X3-159.  1990 ralisation du document nal normalis auprs de l'ISO : ISO/IEC 9899 [ISO89] ;  1999 premire rvision de la norme ISO/IEC 9899 [ISO99]. Jusqu'en 1987, il n'y avait pas de norme. Le livre "The C Programming Language" [BK78] de B. W. Kernighan et D. M. Ritchie dnit le langage. Ce livre contient une description prcise du langage appele [BK88] ainsi que la norme ISO [ISO89] sont la base de ce cours. Le livre de Philippe Dax [Dax92] est lui aussi une bonne introduction pour l'apprentissage de ce langage.

"C Reference Manual". Ce livre qui a lui aussi t remis au gout du jour en 1988

1.2 Prsentation du langage


Le langage C est un langage de bas niveau dans le sens o il permet l'accs des donnes que manipulent les ordinateurs (bits, octets, adresses) et qui ne sont pas souvent disponibles partir de langages volus tels que Fortran, Pascal ou ADA. Le langage C a t conu pour l'criture de systmes d'exploitation et du logiciel de base. Plus de 90% du noyau du systme UNIX est crit en langage C. Le compilateur C lui-mme est crit en grande partie en langage C ou partir d'outils gnrant du langage C [SJ78]. Il en est de mme pour les autres outils de la chane de compilation (assembleur, diteur de liens, pr-processeur). De plus, tous les utilitaires du systme sont crits en C (shell, outils). Il est cependant susamment gnral pour permettre de dvelopper des applications varies de type scientique ou encore pour l'accs aux bases de donnes. Par le biais des bases de donnes, il est utilis dans les applications de gestion. De nombreux logiciels du domaine des ordinateurs personnels, tels que Microsoft Word ou Microsoft Excel, sont eux-aussi crits partir de langage C ou de son successeur orient objet : C++ [Str86]. Bien que pouvant tre considr de bas niveau, le langage C supporte les structures de base ncessaires la conception des applications structures. Cette caractristique le range dans la catgorie des langages de haut niveau. Il est aussi un des premiers langages orant des possibilits de programmation modulaire, c'est--dire qu'un programme de langage C peut tre constitu de plusieurs modules. Chaque module est un chier source que l'on peut compiler de manire autonome pour obtenir un chier objet. L'ensemble des chiers objets participants un programme doivent tre associs pour constituer un chier excutable. Lorsque nous parlons du langage C, dans cette premire partie, nous faisons rfrence ce que sait faire le compilateur lui-mme. Comme nous le verrons plus loin dans la section 1.4, plusieurs outils interviennent dans la transformation d'un ensemble de chiers sources, constituant un programme, en un chier binaire excutable, qui est le rsultat de ce que l'on appelle communment la compilation. Il serait plus juste de dire les compilations suivies par les traductions d'assembleur en objet, suivies de la runion des chiers objets.

Le compilateur de langage C se limite aux fonctionnalits qui peuvent tre traduites ecacement en instructions machine.
La rgle de fonctionnement du compilateur C, dicte ci-dessus, permet de dtecter ce qui est fait directement par le compilateur lui-mme et ce qui ne peut l'tre. Essayons d'illustrer cette rgle par quelques exemples :  Le compilateur C est capable de gnrer des instructions machine qui permettent de manipuler des lments binaires(bits) ou des groupes d'lments binaires. Il peut donc raliser des masques pour slectionner des groupes de bits, ou encore faire des dcalages de bits l'intrieur de mots machine.  Il permet les manipulations algbriques (addition, multiplication, etc.) de groupes d'octets qui reprsentent des valeurs entires ou des valeurs dcimales. c Christian Bac 1985-2003

CHAPITRE 1.

HISTORIQUE ET PRSENTATION

 Il permet de manipuler des caractres en considrant qu'un caractre est reprsent par un octet partir du code ASCII .  Il ne permet pas de manipuler directement des tableaux. En particulier, il ne permet par de manipuler directement les groupes de caractres utiliss pour stocker les chanes de caractres. Pour cela, il faut faire appel des fonctions de bibliothques dont le nom commence par

str comme strcat().

 De manire contradictoire la rgle prcdente, le compilateur accepte l'aectation d'une collection de donnes groupes (structure) par une collection de donnes de type identique, depuis la normalisation du langage. Ceci s'explique par le fait qu'une structure est considre dans le langage comme une donne simple, elle doit donc pouvoir tre aecte une autre donne de mme type. Pour raliser des oprations plus compliques, le programmeur doit crire ses propres fonctions ou faire appel aux fonctions prdnies de la bibliothque du langage C (voir chapitres 16 et 17). Ces fonctions sont, elles aussi, standardises. La rdaction de la norme a supprim un petit problme qui venait de la rfrence sous-jacente aux oprations possibles sur le processeur du PDP 11 de Digital Equipment sur lequel ont t conues les premires versions du compilateur C. Cette machine tait cependant susamment gnrale pour que cela ne transparaisse pas.

1.3 Ides fondamentales


Il est dicile de prsenter les dirents concepts du langage indpendemment les uns des autres, c'est pourquoi, certains concepts, comme la visibilit des variables, sont abords dans les premiers chapitres pour n'tre approfondis que plus tard. Nous allons dcrire les principales composantes d'un programme crit en langage C. Comme il est montr dans la gure 1.1, un programme en C est constitu d'un ensemble de chiers sources destins tre compils sparment et subir une dition de liens commune. Ces chiers sources sont aussi appels modules et ce type de programmation est appel programmation modulaire. Les notions de visibilits associes la programmation modulaire sont approfondies dans le chapitre 9. Le fait de pouvoir compiler chaque chier source de manire autonome amne concevoir des programmes de manire modulaire en regroupant, dans chaque chier source, des fonctions qui manipulent les mmes variables ou qui participent aux mmes algorithmes. Chacune des parties peut tre regroupe dans un ou plusieurs chiers de langage C que l'on appelle aussi module. Prenons pour exemple un programme qui enregistre une srie de noms et notes d'lves. Chaque nom est associ une note. Une fois la saisie termine le programme trie la liste des lves par rang de note et ache cette liste ainsi trie. Puis il trie la liste des lves par ordre alphabtique partir de leurs noms et stocke cette liste dans un chier sur disque. Ce type d'application peut se dcouper en trois parties correspondant la gure 1.1 :  la partie interactive qui change les informations avec l'utilisateur (fichier1.c ;

 la partie stockage des donnes sur disque une fois ces donnes tries (fichier3.c). Chaque chier (voir g. 1.2) contient les lments suivants dans un ordre quelconque :  des rfrences des variables ou des fonctions externes (sous forme de dclarations). Ces rfrences dcrivent les types des variables ou le prototype des fonctions utilises dans ce module mais dnies dans d'autres modules ;  des dnitions de variables globales et de fonctions, qui peuvent tre rfrences

 la partie de calcul qui dans ce cas est un tri (par note ou par nom) (fichier2.c) ;

3 dans les

2 ASCII 3 Nous

: Americans Standard Code for Information Interchange. ISO 646 :1983, Information processing - ISO

7-bit coded character set for information interchange. verrons plus en dtail l'ensemble des possibilits associes aux dclarations et aux dnitions dans les chapitres 3 et 9.

c Christian Bac 1985-2003

1.3.

IDES FONDAMENTALES

Fig.

1.1  Structure d'un programme C

Fig.

1.2  Fichier source

c Christian Bac 1985-2003

CHAPITRE 1.

HISTORIQUE ET PRSENTATION

Fig.
autres chiers ;

1.3  Structure d'une fonction C

 des lignes de directives de compilation (pour le pr-processeur). Une fonction (Fig. 1.3) est construite partir :  d'une interface constitue du type et du nom de la fonction suivis par les types et les noms de ses paramtres ;  d'un bloc, appel aussi corps de la fonction. La fonction

main()

est particularise, en ce sens que l'excution du chier binaire excutable,

conu partir de l'ensemble des chiers source, commence par elle. Un bloc est constitu :  d'une accolade ouvrante ;  des dnitions des variables locales au bloc ;  des instructions ;  d'une accolade fermante. Une instruction peut tre :  un bloc ;

 ou une expression

5 suivie d'un point virgule (

;) ;

 ou une instruction de contrle de ot (test, boucle, rupture de squence). Nous parlerons en dtail des possibilits du pr-processeur dans le chapitre 15.

1.4 En-chaneur de passes


L'tude des direntes actions entreprises lors de ce que nous appelons de manire abusive la compilation, permet de mieux comprendre de quel outils tiques de la programmation en langage C. Nous prenons le cas des outils utiliss dans les systmes de type UNIX car les actions sont facilement sparables. Dans un systme de type UNIX, pour obtenir un chier excutable partir d'un source C, la commande usuelle est proviennent les direntes caractris-

cc6

cc options nom_du_fichier.c
Ces compilateurs sont en fait des en-chaneurs de passes ; nous allons voir l'usage, le fonctionnement, et les options de uvre cinq utilitaires :  le pr-processeur, que nous appellerons  le compilateur C, que nous appellerons

cc.

Cet outils sert appeler les dirents utilitaires ncessaires

la transformation d'un programme C en un chier excutable. L'en-chaneur de passes

cc

met en

cpp ; c0+c1

car il peut tre dcoup en deux parties ;

4 On

voit apparatre une dnition rcursive l'intrieur du langage : savoir un bloc contient des instructions 5.

qui peuvent tre des blocs qui contiennent des instructions, . . .

5 Les expressions sont explicites dans le chapitre 6 cc ou tout autre compilateur comme gcc.

c Christian Bac 1985-2003

1.4. EN-CHANEUR DE PASSES

Fig.

1.4  Schma de fonctionnement de

cc

c Christian Bac 1985-2003

CHAPITRE 1.

HISTORIQUE ET PRSENTATION

 l'optimiseur de code, appel

c2 ;

 l'assembleur, que nous nommerons

as ;

 l'diteur de liens, dont le nom le plus courant est

ld.

La gure1.4 donne un organigramme des direntes actions entreprises par un en-chaneur de passes. Les chiers temporaires de 1 3 dcrits dans cette gure sont utiliss par les outils pour stocker les donnes intermdiaires ncessaires la traduction des dirents codes.

1.4.1 Pr-processeur
Le pr-processeur ou pr-compilateur est un utilitaire qui traite le chier source avant le compilateur. C'est un manipulateur de chanes de caractres. Il retire les parties de commentaires, qui sont comprises entre

/*

et

*/.

Il prend aussi en compte les lignes du texte source ayant un

en

premire colonne pour crer le texte que le compilateur analysera. Ses possibilits sont de trois ordres (voir chap. 15) :  inclusion de chiers ;  dnition d'alias et de macro-expressions ;  slection de parties de texte.

1.4.2 Compilateur
Le compilateur lit ce que gnre le pr-processeur et cre les lignes d'assembleur correspondantes. Le compilateur lit le texte source une seule fois du dbut du chier la n. Cette lecture conditionne les contrles qu'il peut faire, et explique pourquoi toute variable ou fonction doit tre dclare avant d'tre utilise.

1.4.3 Optimiseur de code


L'optimiseur de code limine les parties du code assembleur qui ne sont pas utiles. Il remplace des squences d'instructions par des instructions plus sophistiques et propres au processeur. Cette opration donne un code plus compact et plus rapide. Ensuite, il optimise les sauts. Dans les premires versions de compilateur, il est arriv que sur certaines machines l'optimisation cre de petits problmes qui se rsument par : aprs l'optimisation, le programme ne marche plus.

1.4.4 Assembleur
L'assembleur prend le code gnr par le compilateur, ventuellement modi par l'optimiseur, et gnre un chier en format relogeable. Ce chier possde des rfrences insatisfaites qui seront rsolues par l'diteur de liens. Sur les machines utilisant un systme de type UNIX, ce chier est sux par

.o 7 .

1.4.5 diteur de liens


L'diteur de liens prend le ou les chiers en format relogeable et les associe pour crer un module chargeable. Il se sert de bibliothques pour rsoudre les rfrences indnies, en particulier la bibliothque standard (libc.a). Il utilise aussi un module spcial, de dmarrage du programme. Par dfaut sur un systme de type UNIX, l'diteur de lien met le rsultat de l'dition de liens dans un chier qu'il appelle

crt0.o,

qui contient le code

a.out.

7 De

mauvaises langues prtendent que sur d'autres types de systme un mauvais esprit aurait os les suxer

par .OBJ

c Christian Bac 1985-2003

1.4. EN-CHANEUR DE PASSES

1.4.6 Quelques options de cc


La gure1.4 donne un schma de fonctionnement de passes. Les les plus couramment utilises :

options de l'enchaineur de passes sont prcdes d'un tiret8

cc,

relativement aux options qui lui sont (-). Voici les options

-c -E -S

provoque la gnration d'un module objet non excutable, il s'arrte avant l'dition de liens.

cc -c toto.c toto.o
par .i.

lance le pr-processeur seul,

cpp,

qui crit sur la sortie standard ou gnre un chier sux

cc -E toto.c stdout ou toto.i


gnre le chier assembleur aprs passage du pr-processeur et du compilateur. Le chier est sux par .s.

-O optimise le code gnr (utilisation de c2). -o nom donne le nom au chier excutable au lieu de a.out. -v
cc -o toto toto.c toto option bavarde, cc annonce ce qu'il
fait. Deux options sont utiles sur le compilateur GNU correspondant la norme ANSI :

cc -S toto.c toto.s

gcc

pour forcer la vrication d'une syntaxe

-ansi

avec cette option le compilateur se comporte comme un compilateur de langage C ANSI sans extensions de langage correspondant au C GNU ;

-pedantic
ansi ;

cette option demande au compilateur de refuser la compilation de programme non

-Wall

cette option augmente le nombre de messages d'alerte gnrs par le compilateur lorsqu'il

rencontre des constructions dangereuses. L'utilisation de ces options est recommande lors de l'apprentissage du langage C en utilisant le compilateur

gcc.

8 Selon

la tradition du systme UNIX.

c Christian Bac 1985-2003

Chapitre 2

Gnralits sur la syntaxe


Ce chapitre introduit les premiers concepts indispensables la comprhension d'un programme C, savoir les rgles qui constituent la syntaxe de base du langage. Ces rgles sont utilises par les compilateurs pour dterminer si une srie de caractres correspond un mot rserv, un nom ou une constante.

2.1 Mise en page


Le format du texte est libre. La mise en page n'a aucune signication pour le compilateur. Elle est importante pour la lisibilit du programme. Les lignes de directives de pr-compilation (voir chapitre 15) commencent par un

#.

2.1.1 Identiant
Les identiants sont utiliss pour donner des noms aux direntes entits utiliss dans le langage. Un identiant est construit selon le modle :  partir de l'alphabet :  a-z,

A-Z, 0-9, _ ;

 il peut avoir jusqu' trente et un caractres signicatifs lation. La norme mentionne que les noms

l'intrieur d'une unit de compi-

peuvent tre limits six caractres entre units

de compilation et que les diteurs de liens peuvent ne pas tenir compte des majuscules et  il commence par une lettre ou le soulign  _. minuscules. Cette contrainte n'est pas suivie par les compilateurs modernes.

2.1.2 Espaces lexicaux


Les dirents identiants d'un programme en langage C sont classs dans des espaces lexicaux qui permettent d'isoler les noms selon leur signication. Les espaces lexicaux utiliss par un compilateur C sont les suivants :  le premier espace contient les identiants relatifs aux types synonymes, aux variables et aux fonctions ;  le second espace est rserv aux tiquettes pour les branchements inconditionnels ;  le troisime espace est utilis pour les noms de modles de structures, d'unions ou d'numrations ;  pour chaque modle de structure ou d'union, un espace de noms est cr noms de champs de la structure ou de l'union. c Christian Bac 1985-2003 pour contenir les

10

2.2. MOTS RSERVS

Ces espaces sont isols ce qui permet d'avoir une tiquette qui porte le mme nom qu'une variable mais jamais une fonction qui porte le mme nom qu'une variable.

2.2 Mots rservs


Ce sont les mots prdnis du langage C. Ils ne peuvent pas tre rutiliss pour des identiants. Ils sont relatifs aux dirents concepts du langage :

type des donnes

classes d'allocation constructeurs

char const double float int long short signed unsigned void volatile auto extern register static enum struct typedef union do for while

instructions de boucle slections

ruptures de squence divers

case default else if switch break continue goto return asm entry fortran sizeof

2.3 Constantes
Les constantes servent dans l'expression des tailles, l'initialisation des variables et dans les expressions. Les constantes de type chane de caractres ont un statut particulier : elles permettent de constituer des tableaux de caractres anonymes. Les caractres de ces tableaux peuvent tre constants. Nous approfondirons l'expression des constantes dans la section 3.2 qui traite des types de variables. Voici cependant quelques exemples de constantes :  constante entire :    constante ottante :

10 ; 121.34 ; caractre simple : 'a' ; chane de caractres : "message".

2.4 Instructions
Une

instruction est :

 soit une instruction simple,  soit un instruction compose. Une

instruction simple est toujours termine par un ;.


{}.

Les instructions composes sont contenues entre deux accolades :

c Christian Bac 1985-2003

Chapitre 3

Types et variables
variable a les rles suivants :
Ce chapitre traite des dnitions de variables. Dans tous les langages, une

dnition de

1. dnir le domaine de valeur de cette variable (taille en mmoire et reprsentation machine) ;

2. dnir les oprations possibles sur cette variable ; 3. dnir le domaine de visibilit de cette variable ; 4. permettre l'environnement d'excution du programme d'associer le nom de la variable une adresse mmoire ; 5. initialiser la variable avec une valeur compatible avec le domaine de valeur. En langage C, une variable se caractrise partir de son type et de sa classe mmoire. Les points prcdents numros 1 et 2 sont associs au type de la variable ; les points 3 et 4 sont associs la classe mmoire de la variable. L'initialisation est traite dans la section3.7.

3.1 Types de base


Ce sont les types prdnis du compilateur. Ils sont au nombre de six :

void int

c'est le type vide. Il a t introduit par la norme ANSI. Il est surtout utilis pour prciser les fonctions sans argument ou sans retour. Il joue un rle particulier dans l'utilisation des pointeurs (voir chapitre 10).

c'est le type entier. Ce type se dcline avec des qualicatifs pour prciser sa taille (long ou

short), et le fait qu'il soit uniquement positif (unsigned) ou positif et ngatif (signed) 1 . Le qualicatif signed est appliqu par dfaut, ainsi il n'y a pas de dirence entre une variable de type int et une variable de type signed int.
ce type est trs proche de l'octet. Il reprsente un entier sur huit bits. Sa valeur peut voluer entre -128 et +127. Il est le support des caractres au sens commun du terme. Ces caractres sont reprsents par la table ASCII. Comme le type

char

int

le type

char

peut tre quali de Il est dni dans le

manire tre sign ou non. La norme ANSI introduit un type permettant de supporter des alphabets comprenant plus de 255 signes, ce type est appel chier<stddef.h>.

wchar_t.

float ce type sert pour les calculs avec des parties dcimales. double c'est un type qui permet de reprsenter des valeurs ayant une partie dcimale avec une plus grande prcision que le type float. Comme nous le verrons dans l'expression des constantes
1 Dans
le cas le plus courant une variable du type entier peut contenir une valeur positive ou ngative.

c Christian Bac 1985-2003

12

3.1. TYPES DE BASE

(sec. 3.2.2) et dans les calculs(sec. 3.8), ce type est le plus courant pour reprsenter des valeurs avec parties dcimales.

long double

ce type est rcent, il permet de reprsenter des nombres avec parties dcimales qui

ncessitent une trs grande prcision.

3.1.1 Types entiers


Les mots

short

et

long
ou

d'avoir des dnitions du type : manire abrge :

short

int, donnant la possibilit short int ou long int. Ces dnitions peuvent aussi s'crire de long.
peuvent tre utiliss seuls ou avec le mot

Le langage C considre les types

char, short int, int

et

long int,

comme des types entiers

et permet de les mlanger lors des calculs (5.3). A priori, les types entiers sont signs, c'est--dire qu'ils peuvent contenir des valeurs positives ou ngatives. Par exemple, la valeur d'une variable du type

char peut voluer entre -128 et +127. unsigned

Les types entiers peuvent tre qualis l'aide du mot type

qui force les variables de

ce type tre considres comme uniquement positives. Par exemple, la valeur d'une variable du

unsigned char

ne peut voluer qu'entre

et

255.

Le qualicatif

signed

permet d'insister sur le fait que la variable peut prendre des valeurs

positives ou ngatives. Il fait pendant au qualicatif pendant l'oprateur  - unaire.

unsigned

comme l'oprateur  + unaire fait

3.1.2 Types avec parties dcimales


Comme nous l'avons dj dit, les types avec parties dcimales sont au nombre de trois :

float

ce type sert pour les calculs avec des parties dcimales. Il est souvent reprsent selon la

norme ISO/IEEE 754.

double

ce type de plus grande prcision permet de reprsenter des valeurs avec parties dcimales.

Lui aussi est souvent bas sur la norme ISO/IEEE 754.

long double

ce type est rcent et permet de reprsenter des nombres avec parties dcimales sur

une trs grande prcision, si la machine le permet.

3.1.3 Tailles des types


L'espace qu'occupent les dirents types en mmoire dpend de la machine sur laquelle est implant le compilateur. Le choix est laiss aux concepteurs des compilateurs. Les seules contraintes sont des ingalits non strictes, savoir :

sizeof (short) sizeof (int) sizeof (long ) sizeof (f loat) sizeof (double) sizeof (longdouble) sizeof est un oprateur qui donne la taille en nombre d'octets
 

du type dont le nom est entre

parenthses. La taille de l'entier est le plus souvent la taille des registres internes de la machine, c'est par exemple seize bits sur une machine de type ordinateur personnel machines du type station de travail. La taille des variables ayant une partie dcimale est le plus souvent cadre sur la norme ISO/IEEE 754. Les machines supportant un type assez rares.

2 et trente-deux bits sur les

long double

dirent du type

double

sont

2 Pour

des problmes de compatibilit avec les anciennes versions, les compilateurs pour PC gnrent le plus

souvent du code compatible 386.

c Christian Bac 1985-2003

CHAPITRE 3.

TYPES ET VARIABLES

13

Type Anne
char short int long oat double long double

PDP 11 Intel 486 Sparc Pentium 1970 1989 1993 1993


8 bits 16 bits 16 bits 32 bits 32 bits 64 bits 64 bits 8bits 16 bits 16 bits 32 bits 32 bits 64 bits 64 bits 8bits 16 bits 32 bits 32 bits 32 bits 64 bits 64 bits 8bits 16 bits 32 bits 32 bits 32 bits 64 bits 64 bits

Alpha 1994
8bits 16 bits 32 bits 64 bits 32 bits 64 bits 128 bits

Tab.

3.1  Longueur des types de base sur quelques machines

Le tableau 3.1 donne quelques exemples de tailles pour des machines dont les registres ont les tailles suivantes en nombre de bits : 16 (DEC PDP11, Intel 486), 32 (SUN Sparc, Intel Pentium) et 64 (DEC Alpha). Vous remarquerez que malgr son architecture interne de 64 bits, le compilateur pour alpha utilise des entiers sur 32 bits. Il est aussi le seul processeur capable de direncier les

double

des

long doubles.

3.2 Constantes associes aux types de base


Les constantes sont reconnues par le compilateur grce l'utilisation de caractres qui ne participent pas la construction d'un identiant.

3.2.1 Constantes de type entier


Les constantes de type entier sont construites partir de chires. Elles sont naturellement exprimes en base dix mais peuvent tre exprimes en base huit (octal) lorsque le premier caractre est un

ou en base seize lorsque les deux premiers caractres sont

0X

(hexadcimal).

Une constante est a priori du type

int

si le nombre qu'elle reprsente est plus petit que le

plus grand entier reprsentable. Si la valeur de la constante est suprieure au plus grand entier reprsentable, la constante devient du type

long.

long int.

Les constantes peuvent tre suxes par un  l ou  L pour prciser que leur type associ est

Les constantes peuvent tre prcdes par un signe  - ou  +. Elles peuvent tre suxes par un  u ou  U pour prciser qu'elles expriment une valeur sans signe (qualies

unsigned).

Voici quelques exemples de constantes de type entier :  constante sans prcision de type :

0377 octal 0X0FF hexadcimal 10 dcimal -20 dcimal


 constante longue entire : 1. 2.

120L, 0364L, 0x1faL 120l, 0364l, 0x1fal 120U, 0364U, 0x1faU


c Christian Bac 1985-2003

 constante entire non signe : 1.

14

3.2.

CONSTANTES ASSOCIES AUX TYPES DE BASE

2.

120u, 0364u, 0x1fau 120UL, 0364UL, 0x1faUL, 120uL, 0364uL, 0x1fauL 120Ul, 0364Ul, 0x1faUl, 120ul, 0364ul, 0x1faul

 constante longue entire non signe : 1. 2.

3.2.2 Constantes avec partie dcimale


Les constantes avec partie dcimale ont le type

double par dfaut. Elles peuvent tre exprimes

partir d'une notation utilisant le point dcimal ou partir d'une notation exponentielle. Ces constantes peuvent tre suxes par un  f ou  F pour prciser qu'elles reprsentent une valeur de type

float.

long double.

Elles peuvent de mme tre suxes par un  l ou un  L pour exprimer des valeurs de type

Voici quelques constantes avec partie dcimale :

121.34

12134e-2 la mme constante exprime en notation exponentielle +12134E-2 la notation exponentielle accepte le  E majuscule, et le  + un-aire. 121.34f constante de valeur identique mais de type float car suxe par f. 121.34l constante de valeur identique mais de type long double car suxe par  l.

double.

constante exprime avec la notation utilisant le point dcimal, son type implicite est

3.2.3 Constantes de type caractre


Les constantes du type caractre simple sont toujours entoures d'apostrophes (single Elles peuvent tre reprsentes selon quatre mthodes : 1. lorsque le caractre est disponible au clavier sauf pour la barre de fraction inverse et l'apostrophe, le caractre correspondant est simplement entour d'apostrophes, par exemple

quote ).

'a'.

2. un caractre peut aussi tre reprsent par sa valeur exprime dans la table ASCII en utilisant une notation en base huit. Cette valeur est prcde l'intrieur des apostrophes par une barre de fraction inverse.

'\0' : octet du nul, il sert dlimiter les ns de chanes de caractres. '\012' : saut de ligne (Line Feed, LF) ; '\015' : retour chariot (Carriage Return, CR) ; '\011' : tabulation horizontale (Horizontal Tabulation, HT) ;
3. de mme, un caractre peut tre reprsent par sa notation en base seize.

'\x0' : caractre nul ; '\xA' : saut de ligne (LF) ; '\xC ' : retour chariot (CR) ; '\x9' : tabulation horizontale '\a' : alert (sonnerie, BEL) ; '\b' : backspace (BS) ; '\f ' : saut de page (FF) ; '\n' : saut de ligne (LF) ;

(HT) ;

4. un certain nombre d'abrviations est aussi disponible :

c Christian Bac 1985-2003

CHAPITRE 3.

TYPES ET VARIABLES

15

Fig.
'\r' '\t' '\v '

3.1  Chane de caractres constante

: retour chariot (CR) ; : tabulation horizontale (HT) ; : tabulation verticale (VT) ;

Pour spcier qu'une constante caractre est du type (wchar_t), elle doit tre prcde d'un L. Par exemple,

L'a'

est la constante de type caractre long contenant le caractre a.

3.2.4 Chanes de caractres


Les constantes du type chane de caractres doivent tre mises entre guillemets (double

quote ).

Le compilateur gnre une suite d'octets termine par un caractre nul (tous les bits 0) partir des caractres contenus dans la chane. Cette suite d'octets peut tre place par le systme dans une zone de mmoire en lecture seulement. La zone correspondante est en fait un tableau de du tableau. Par exemple, la chane de caractres le schma de la gure 3.1.

char. La chane est rfrence par l'adresse "message" est gnre par le compilateur selon

3.3 Qualicatifs
Nous avons dj parl des qualicatifs

unsigned

et

signed

qui s'appliquent aux variables de

type entier. Il existe d'autres qualicatifs qui ont t spcis par la norme. Il s'agit de

volatile, static

et

register.

const,

Une dnition de variable qualie du mot

const informe le compilateur que cette variable est

considre comme constante et ne doit pas tre utilise dans la partie gauche d'une aectation. Ce type de dnition autorise le compilateur placer la variable dans une zone mmoire accessible en lecture seulement l'excution. Le qualicatif

volatile informe le compilateur que la variable correspondante est place dans

une zone de mmoire qui peut tre modie par d'autres parties du systme que le programme lui-mme. Ceci supprime les optimisations faites par le compilateur lors de l'accs en lecture de la variable. Ce type de variable sert dcrire des zones de mmoire partages entre plusieurs programmes ou encore des espaces mmoires correspondant des zones d'entre-sorties de la machine. Les deux qualicatifs peuvent tre utiliss sur la mme variable, spciant que la variable n'est pas modie par la partie correspondante du programme mais par l'extrieur. Les qualicatifs

static

et

register

sont dcrits dans la section 3.5.

3.4 Taille et normalisation


Les tailles des types entiers et avec partie dcimale sont dnies sur chaque machine partir de deux chiers :

limits.h float.h

pour les types entiers ;

pour les types avec partie dcimale. c Christian Bac 1985-2003

16

3.5.

DFINITION DE VARIABLES

Ces chiers contiennent des dnitions qui s'adressent au pr-compilateur et donnent les tailles et valeurs maximales des types de base et des types non signs. Le programme 3.1 est un exemple de chier de chier

<float.h>.

<limits.h>

et le programme 3.2 est un exemple

Programme 3.1 Exemple de chier limits.h


/* Number of bits in a char. */ #define CHAR_BIT 8 /* No multibyte characters supported yet. #define MB_LEN_MAX 1 */ */

/* Min and max values a signed char can hold. #define SCHAR_MIN (-128) #define SCHAR_MAX 127 /* Max value an unsigned char can hold. #define UCHAR_MAX 255U /* Min and max values a char can hold. #define CHAR_MIN SCHAR_MIN #define CHAR_MAX SCHAR_MAX

(Min is 0). */ */

/* Min and max values a signed short int can hold. #define SHRT_MIN (-32768) #define SHRT_MAX 32767

*/

/* Max value an unsigned short int can hold. (Min is 0). */ #define USHRT_MAX 65535U /* Min and max values a signed int can hold. #define INT_MIN (-INT_MAX-1) #define INT_MAX 2147483647 /* Max value an unsigned int can hold. #define UINT_MAX 4294967295U */

(Min is 0). */ */

/* Min and max values a signed long int can hold. #define LONG_MIN (-LONG_MAX-1) #define LONG_MAX 2147483647

/* Max value an unsigned long int can hold. (Min is 0). */ #define ULONG_MAX 4294967295U

La normalisation a aussi introduit un ensemble de types prdnis comme type de la valeur retourne par l'oprateur le chier

<stddef.h>.

sizeof.

size_t

qui est le

Les dnitions exactes de ces types sont dans

Le programme 3.3 est un extrait d'un exemple de chier

<stddef.h>.

3.5 Dnition de variables


Nous appellerons associs la

identiant soit un nom de fonction, soit un nom de variable. Pour complter

ce que nous avons dit dans l'introduction de ce chapitre, voici comment les dirents besoins

dnition de variables sont couverts par le langage C : dnition du domaine de valeur de cette variable et les oprations lgales sur cette variable ;
=
grce au type. c Christian Bac 1985-2003

CHAPITRE 3.

TYPES ET VARIABLES

17

Programme 3.2 Exemple de chier float.h


/* #define #define #define #define #define #define #define #define #define /* #define #define #define #define #define #define #define #define #define Float definitions */ FLT_MANT_DIG FLT_EPSILON FLT_DIG FLT_MIN_EXP FLT_MIN FLT_MIN_10_EXP FLT_MAX_EXP FLT_MAX FLT_MAX_10_EXP 24 1.19209290e-07f 6 -125 1.17549435e-38f -37 128 3.40282347e+38f 38

Double definitions */ DBL_MANT_DIG DBL_EPSILON DBL_DIG DBL_MIN_EXP DBL_MIN DBL_MIN_10_EXP DBL_MAX_EXP DBL_MAX DBL_MAX_10_EXP 53 2.2204460492503131e-16 15 -1021 2.2250738585072014e-308 -307 1024 1.79769313486231570e+308 308

Programme 3.3 Exemple de chier stddef.h


typedef long ptrdiff_t; typedef unsigned long size_t; typedef int wchar_t;

rservation de l'espace mmoire


=

ncessaire au support de la variable lors de l'excution ;

grce au type et la classe mmoire. l'aide d'une constante dont le type correspond celui de la va-

initialisation de la variable
riable ;

en faisant suivre le nom par un symbole d'aectation

et une valeur compatible avec

la variable.

association d'une dure de vie


=

la variable qui permet l'utilisation dans certaines parties du

programme (rgles de visibilit). grce la classe mmoire et au lieu de dnition.

Une dnition de variable est l'association d'un identiant un type et la spcication d'une classe mmoire. La

classe mmoire sert expliciter la visibilit d'une variable et son implantation classes mmoire sont :

en machine. Nous approfondirons les possibilits associes aux classes mmoire dans le chapitre 9 sur la visibilit. Les

global

cette classe est celle des variables dnies en dehors d'une fonction. Ces variables sont

accessibles toutes les fonctions. La dure de vie des variables de type global est la mme que celle du programme en cours d'excution.

local

ou

auto : cette classe comprend l'ensemble des variables dnies dans un bloc. C'est le cas

de toute variable dnie l'intrieur d'une fonction. L'espace mmoire rserv pour ce type de variable est allou dans la pile d'excution. C'est pourquoi elles sont appeles aussi

auto

c.a.d automatique car l'espace mmoire associ est cr lors de l'entre dans la fonction et c Christian Bac 1985-2003

18

3.6. TYPES DRIVS DES TYPES DE BASE

Dclaration/dnition

Classe mmoire dnition d'une variable globale paramtres passs dans la pile, donc automatiques dnition d'une variable locale main donc automatique variable locale main mais implante avec les globales dclaration d'une variable qui est dnie dans un autre chier (rien voir la variable

int a ; int main (int argc, char *argv[]) { int b ; static char c[50] ; } extern int b ; int coucou(const int c) { volatile char c ; register int a ; if (b == 1) }

de main), variable globale externe

paramtre constant, variable locale la fonction coucou s'engage ne pas modier c variable locale volatile variable locale coucou, mettre en registre si possible rfrence la variable b externe

Tab.
static

3.2  Variables et classes mmoire

il est dtruit lors de la sortie de la fonction. La dure de vie des variables de type local est celle de la fonction dans laquelle elles sont dnies. ce qualicatif modie la visibilit de la variable, ou son implantation : l'espace de mmoire globale pour cette variable. Une variable locale de type statique a un nom local mais a une dure de vie gale celle du programme en cours d'excution.  dans le cas d'une variable globale, ce prdicat restreint la visibilit du nom de la variable l'unit de compilation. Une variable globale de type statique ne peut pas tre utilise par un autre chier source participant au mme programme par une rfrence avec le mot rserv

 dans le cas d'une variable locale il modie son implantation en attribuant une partie de

extern

(voir point suivant).

extern

ce qualicatif permet de spcier que la ligne correspondante n'est pas une tentative de

dnition mais une

dclaration (voir 3.9). Il prcise les variables globales (noms et types)

qui sont dnies dans un autre chier source et qui sont utilises dans ce chier source.

register

ce qualicatif permet d'informer le compilateur que les variables locales dnies dans

le reste de la ligne sont utilises souvent. Le prdicat demande de les mettre si possible dans des registres disponibles du processeur de manire optimiser le temps d'excution. Le nombre de registres disponibles pour de telles demandes est variable selon les machines. Il est de toute faon limit (4 pour les donnes, 4 pour les pointeurs sur un 680X0). Seules les variables locales peuvent tre qualies

register.

Le tableau 3.2 donne quelques exemples de dnitions et dclarations de variables.

3.6 Types drivs des types de base


Un type driv est cr partir des types de base vus prcdemment pour l'usage propre un programme. Les types drivs sont les

tableaux, les structures et les pointeurs.

3.6.1 Tableaux et structures


Les tableaux sont des paquets de donnes de mme type. Ils sont reconnus par la prsence de crochets ouvrants et fermants lors de la dclaration ou de la dnition de l'objet. La taille du c Christian Bac 1985-2003

CHAPITRE 3.

TYPES ET VARIABLES

19

tableau est donne entre les crochets lors de la dnition. Pour simplier le travail du compilateur, le rang des lments du tableau ne peut voluer qu'entre 0 et la taille du tableau -1. Les structures sont des ensembles de donnes non homognes. Les donnes peuvent avoir des types dirents. Les structures sont dclares ou dnies selon le modle :  struct  un nom de structure facultatif  

{ }

 la liste des donnes contenues dans la structure  la liste des variables construites selon ce modle. Prenons pour exemple les dnitions suivantes :

int tab[10]; struct st1 { int a1; float b1; long c1; } objst1;
Dans cet exemple : 1.

tab st1

est un tableau de 10 entiers, et les lments du tableau sont rfrencs par

jusqu' 2.

tab[9] ;

tab[0]

est un nom de modle de structure et

direntes parties de la structure

objst1.c1.

objst1

objst1

est un objet de type

sont accessibles par

struct st1. Les objst1.a1, objst1.b1 et

Les tableaux et les structures sont parfois appels agglomrats de donnes.

3.6.2 Pointeurs
Le

pointeur est une variable destine contenir une adresse mmoire. Le compilateur connais*) qui

sant la taille de l'espace adressable de la machine, il sait la taille ncessaire pour contenir un pointeur. Un pointeur est reconnu syntaxiquement par l'toile (symbole de la multiplication prcde son nom dans sa dnition. Tout pointeur est associ un type d'objet. Ce type est celui des objets qui sont manipulables

grce au pointeur. Ce type est utilis en particulier lors des calculs d'adresse qui permettent de manipuler des tableaux partir de pointeurs (voir Chap. 10). Prenons les dnitions suivantes :

int *ptint; char *ptchar;


Dans cet exemple,

peut donc contenir des De mme,

3 valeurs qui sont des adresses de variables du type entier (int).

ptint

est une variable du type

pointeur sur un entier. Cette variable

des valeurs qui sont des adresses de variables de type caractre (char).

ptchar

est une variable du type pointeur sur un caractre. Elle peut donc contenir

Le compilateur C vrie le type des adresses mises dans un pointeur. Le type du pointeur conditionne les oprations arithmtiques (voir chap. 9 pointeurs et tableaux) sur ce pointeur. Les oprations les plus simples sur un pointeur sont les suivantes :

3 Une

valeur la fois mais comme le pointeur est une variable cette valeur peut changer au cours de l'excution

du programme.

c Christian Bac 1985-2003

20

3.7. INITIALISATION DE VARIABLES

 aectation d'une adresse au pointeur ;  utilisation du pointeur pour accder l'objet dont il contient l'adresse. Si l'on dnit les variables de la manire suivante :

int int char int char

in; tabint[10]; car; *ptint; *ptchar; &

Un pointeur peut tre aect avec l'adresse d'une variable ayant un type qui correspond celui associ au pointeur. Comme nous le verrons dans la partie sur les oprateurs, le -commercial donne l'adresse du nom de variable qui le suit et les noms de tableau correspondent l'adresse du premier lment du tableau. Les pointeurs prcdents peuvent donc tre aects de la manire suivante :

ptint = &in; ptc = &car;


Une fois un pointeur aect avec l'adresse d'une variable, ce pointeur peut tre utilis pour accder aux cases mmoires correspondant la variable (valeur de la variable) :

*ptint = 12; *ptc = 'a';


La premire instruction met la valeur entire 12 dans l'entier le caractre a minuscule dans l'entier

car.

in ;

la deuxime instruction met

Il est possible de raliser ces oprations en utilisant le pointeur pour accder aux lments du tableau. Ainsi les lignes :

ptint=tab; *ptint=4;
aectent le pointeur lment du tableau nous le reverrons dans le chapitre sur pointeurs et tableaux 10)

ptint avec l'adresse du premier lment du tableau tabint quivalent (comme &tabint[0] ; puis le premier (tabint[0]) est aect avec la valeur 4.

3.7 Initialisation de variables


L'initialisation se dnit comme l'aectation d'une valeur lors de la dnition de la variable. Toute modication de valeur d'une variable postrieure sa dnition n'est pas une initialisation mais une aectation. Par dfaut, les variables de type global (dnies en dehors de toute fonction) sont initialises avec la valeur qui correspond tous les bits zro (0 pour un entier ou 0.0 pour un nombre virgule ottante). Les variables locales, quant elles ne sont pas initialises avec des valeurs par dfaut. Vous veillerez donc les initialiser pour vous prmunir contre le risque d'utiliser une variable sans en connatre la valeur initiale. Sur les compilateurs anciens, pour les variables de type tableau ou structure, seules les variables globales pouvaient tre initialises. Il est possible de raliser des initialisations selon trois techniques suivant le type de la variable : 1. dans le cas d'une variable simple, il sut de faire suivre la dnition du signe gal (=) et de la valeur que l'on veut voir attribue la variable. c Christian Bac 1985-2003

CHAPITRE 3.

TYPES ET VARIABLES

21

int i = 10; int j = 12, k = 3, l; int *p1 = &i; char d = '\n'; float tf[10] = { 3.1, 4.5, 6.4, 9.3 }; char t1[10] = "Coucou"; struct tt1{ int i; float j; char l[20]; } obst = { 12, 3.14, "qwertyuiop" }; char t2[] = "bonjour"; char t3[10] = { 'a', 'b','c','d','e'}; const char *p3 = "Bonjour les";

Entier i initialis 10 entiers j initialis 12 ; k initialis 3 et l non initialis. Pointeur d'entier initialis l'adresse de i Caractre initialis la valeur du retour chariot. Tableau de dix ottants dont les quatre premiers sont initialiss 3.1 4.5 6.4 et 9.3, les autres sont initialiss 0.0. Tableau de 10 caractres initialis avec les caractres

'C' 'o' 'u' 'c' 'o' 'u' '\0'


initialiss avec la valeur un entier, un ottant, et un tableau de 20 caractres. variable (obst) du type

Les trois derniers caractres sont aussi

'\0'.

modle de structure contenant

avec le premier champ (obst.i) initialis 12, le deuxime champ (obst.j) initialis 3.14, de la chane "qwertyuiop" Tableau de caractres initialis avec la chane "bonjour". La taille du tableau est calcule selon le nombre de caractres + 1 (pour le nul). Tableau de 10 caractres dont les 5 premiers sont initialiss. Pointeur sur un caractre initialis l'adresse de la chane de caractres constante. La chane peut tre mise dans une zone de mmoire accessible en lecture seulement. et le troisime champ (obst.l) initialis partir

struct tt1,

Tab.

3.3  Exemples d'initialisations

2. dans le cas de tableaux ou structures, il faut faire suivre la dnition du signe gal suivi d'une accolade ouvrante et de la srie de valeurs termine par une accolade fermante. Les valeurs sont spares par des virgules. Elles doivent correspondre aux lments du tableau ou de la structure. La norme prconise que lorsque le nombre de valeurs d'initialisation est infrieur au nombre d'lments initialiser, les derniers lments soient initialiss avec la valeur nulle correspondant leur type. 3. les tableaux de caractres peuvent tre initialiss partir d'une chane de caractres. Les caractres de la chine sont considrs comme constants. Le tableau 3.3 donne des exemples d'initialisation.

3.8 Conversion de type


La conversion de type est un outil trs puissant, elle doit donc tre utilise avec prudence. Le compilateur fait de lui-mme des conversions lors de l'valuation des expressions. Pour cela il applique des rgles de conversion implicite. Ces rgles ont pour but la perte du minimum d'information dans l'valuation de l'expression. Ces rgles sont dcrites dans l'encart ci-dessous. c Christian Bac 1985-2003

22

3.8.

CONVERSION DE TYPE

float f ; double d ; int i ; long li ; li = f + i ; i est transform en oat puis additionn d = li + i ; i = f + d;

f,

le rsultat est transform en long et rang dans li. i est transform en long puis additionn li, le rsultat est transform en double et rang dans d. f est transform en double, additionn d, le rsultat est transform en int et rang dans i.

Tab.

3.4  Exemples de conversion implicite

Rgle de Conversion Implicite

Convertir les lments de la partie droite d'une expression d'aectation dans le type de la variable ou de la constante le plus riche. Faire les oprations de calcul dans ce type. Puis convertir le rsultat dans le type de la variable aecte.
La notion de richesse d'un type est prcise dans la norme [ISO89]. Le type dans lequel le calcul d'une expression deux oprandes doit se faire est donn par les rgles suivantes : 1. si l'un des deux oprandes est du type

long double ; double ;

long double alors le calcul doit tre fait dans le type double
alors le calcul doit tre fait dans le

2. sinon, si l'un des deux oprandes est du type type

3. sinon, si l'un des deux oprandes est du type

float ;

float alors le calcul doit tre fait dans le type

4. sinon, appliquer la rgle de promotion en entier, puis : (a) si l'un des deux oprandes est du type dans ce type ; (b) si l'un des deux oprandes est du type type

unsigned long int alors le calcul doit tre fait long int
alors le calcul doit tre fait dans le

long int ;

(c) si l'un des deux oprandes est du type le type

unsigned int ;

unsigned int

alors le calcul doit tre fait dans

(d) si l'un des deux oprandes est du type

int alors le calcul doit tre fait dans le type int.

3.8.1 Conversions implicites


Le C selon la rdaction de Kernighan et Ritchie dcrivait la faon avec laquelle les variables taient promues lors des appels de fonction. Cette rgle porte d'une part sur les nombres virgule ottante qui sont transfoms en

double,

et d'autre part sur tous les types entier dont la taille est

plus petite que l'entier naturel. Les variables ou les constantes des types suivants sont utilises dans une expression, les valeurs de ces variables ou constantes sont transformes en leur quivalent en entier avant de faire les calculs. Ceci permet d'utiliser des caractres, des entiers courts, des champs de bits et des numrations de la mme faon que des entiers. Le principe permet d'utiliser la place d'un entier :  des caractres et des entiers courts signs ou non signs ;  des champs de bits et des numrations signs ou non signs. Des exemples de conversions implicites sont donns dans le tableau3.4. Il est possible de forcer la conversion d'une variable (ou d'une expression) dans un autre type avant de l'utiliser par une conversion implicite. Cette opration est appele cast. Elle se ralise de la manire suivante : c Christian Bac 1985-2003

CHAPITRE 3.

TYPES ET VARIABLES

23

(type) expression
Prenons pour exemple l'expression :

i = (int) f + (int) d ;

f et d sont convertis en int, puis additionns. Le rsultat entier est rang dans i.

i = f + d ;
et

Il peut y avoir une dirence entre

i = (int) f + (int) d ;
du fait de la perte des parties fractionnaires.

3.9 Dclaration et dnition


Maintenant que nous connaissons les dirents types du langage C, nous pouvons introduire la dirence entre dclaration et dnition. Cette dirence sera vue de manire approfondie dans le chapitre 9. Nous appellerons : 

dclaration : une association de type avec un nom de variable ou de fonction (dans ce cas
: une dclaration et si c'est une variable, une demande d'allocation d'espace

la dclaration contient aussi le type des arguments de la fonction, les noms des arguments peuvent tre omis), 

dnition

pour cette variable, si c'est une fonction la dnition du corps de fonction contenant les instructions associes cette fonction. De manire simpliste, une dclaration fait rfrence une dnition dans une autre partie du programme. Elle peut se traduire par je sais qu'il existe une variable ayant ce type et portant ce nom.

3.10 Exercices sur les types et variables


3.10.1 Exercice 1
Dans un chier appel

exo1.c,

dclarer les variables suivantes :

 chane de 10 caractres globale et statique ;  tableau de 10 entiers global ;  pointeur sur caractre local en registre ;  ottant local ;  caractre local statique ;  entier nomm ex externe. Dans la fonction

main(),

faire crire les adresses des variables.

Compiler avec :

gcc -c exo1.c exo1bis.c


mettre la dnition de l'entier

Dans un deuxime chier appel liserez avec la valeur 20.

ex

que vous initia-

Compiler ce deuxime chier de la mme manire : Faire l'dition de liens par :

gcc -c exo1bis.c

gcc -o exo1 exo1.o exo1bis.o

3.10.2 Exercice 2
Dans un chier appel

exo2.c,

dclarer les variables suivantes :

 un entier global initialis 10 ;  un tableau de 10 caractres global initialis

"bonjour" ;

c Christian Bac 1985-2003

24

3.10.

EXERCICES SUR LES TYPES ET VARIABLES

Programme 3.4 Suggestion de corrig chapitre 3 exercice 1


1 2 3 4 5 6 7 8 9 10 static char chaine[10]; int tableau[10]; extern int ex; int main (int argc, char *argv[], char **envp){ register char *pointeur; float local; static char car; return 0; }

Programme 3.5 Suggestion de corrig chapitre 3 exercice 1 second chier


1 2 int ex = 20;

 un pointeur sur caractre initialis l'adresse du premier lment du tableau. Compiler, essayer de mettre l'adresse de l'entier dans le pointeur de caractre et regardez les messages d'erreurs. Une fois que vous aurez lu le chapitre 4 sur les lments de bases pour raliser les premiers programmes, faire crire le tableau partir de son nom et avec le pointeur.

Programme 3.6

1 2 3 4 5 6 7 8 9 10 11 12

/* declaration des variables globales */ int global = 10; char tableau[10] = "bonjour"; int main (int argc, char *argv[], char **envp){ char *pt = tableau; /* ou pt = & tableau[0] */ pt = (char *) &global; /* adresse de l entier dans le pointeur de char */ pt = tableau; /* adresse du tableau dans le pointeur */ printf("%s\n", tableau); printf("%s\n", pt); return 0; }

Suggestion de corrig chapitre 3 exercice 2

Donnes crites sur le fichier standard de sortie


bonjour bonjour

3.10.3 Exercice 3
Dclarer :  un entier  un ottant

i; f;

 un pointeur sur caractre  un pointeur sur entier  un tableau d'entier

ti ;

ptc ; pti ;

c Christian Bac 1985-2003

CHAPITRE 3.

TYPES ET VARIABLES

25

 un tableau de caractres      

tc.

Raliser les oprations suivantes :

i = f = pti ptc pti ptc

f; i; = 0; = pti ; = tc ; = ti.

Compiler. Faire les "casts" ncessaires une compilation sans erreurs.

Programme 3.7 Suggestion de corrig chapitre 3 exercice 3


1 int 2 main (int argc, char *argv[], char **envp){ 3 /* declarations des variables */ 4 int i; 5 float f; 6 char *ptc; 7 int *pti; 8 int ti[10]; 9 char tc[10]; 10 /* affectations des variables */ 11 i = f; 12 f = i; 13 pti = 0; 14 ptc = (char *) pti; 15 pti = (int *) tc; 16 ptc = (char *) ti; 17 return 0; 18 }

3.10.4 Exercice 4
Dnir les variables :          

i entier f ottant l long c caractre tc tableau de

caractres. 50 ;

en les initialisant de la manire suivante :

i la valeur hexadcimale f a 3.14 ; l la valeur octale 40 ; c z ; tc "qwertyuiop".

c Christian Bac 1985-2003

26

3.10.

EXERCICES SUR LES TYPES ET VARIABLES

Programme 3.8 Suggestion de corrig chapitre 3 exercice 4

1 int 2 main (int argc, char *argv[], char **envp){ 3 /* declaration et initialisation des variables */ 4 int i = 50; 5 float f = 3.1415927; 6 long l = 040L; 7 char c = 'z'; 8 static char tc[] = "qwertyuiop"; 9 return 0; 10 }

c Christian Bac 1985-2003

Chapitre 4

Elments de base
Le langage C est utilis dans un contexte interactif. Ce qui veut dire que la plupart des programmes crits en langage C font des changes d'information avec un utilisateur du programme. Bien sr, le langage C est un langage des annes 70 et l'ide de l'interaction avec l'utilisateur est celle des systmes centraliss temps partag. Un utilisateur de ce type de systme est connect via une voie d'entre-sortie qui permet d'changer des caractres. Ces voies sont la plupart du temps relies un tltype (cran, clavier, avec sortie optionnelle sur papier). Les caractres sont crits sur l'cran du terminal et lus partir du clavier. Ce modle cran clavier qui est repris par le systme UNIX est celui des interactions en langage C partir des chiers standard d'entre et de sortie. Les entre-sorties en langage C ne sont pas prises en charge directement par le compilateur mais elles sont ralises travers des fonctions de bibliothque. Le compilateur ne peut pas faire de contrle de cohrence dans les arguments passs ces fonctions car ils sont de type variable. Ceci explique l'attention toute particulire avec laquelle ces oprations doivent tre programmes.

4.1 Bonjour
Le premier programme que tout un chacun crit lorsqu'il apprend un nouveau langage rpond la question suivante : comment crire un programme principal qui imprime programme est donn dans la gure 4.1. Il est constitu de la manire suivante :  la premire ligne est une directive pour le pr-processeur qui demande celui-ci de lire le chier reprsentant l'interface standard des entres sorties. Le contenu de ce chier est dcrit

Bonjour ?

Ce

Fig.

4.1  Programme qui crit Bonjour

c Christian Bac 1985-2003

28

4.2.

LIRE ET CRIRE

de manire approfondie dans le chapitre 16. Cette premire ligne doit tre prsente dans tout module faisant appel des fonctions d'entres sorties et en particulier aux fonctions et

scanf() ;

printf()

 il n'y a pas de variable globale ;  le programme contient une seule fonction Cette fonction est utilise sans argument ;  la dnition de la fonction ouvrante ;  elle ne contient pas de variable locale ;

main()

qui joue le rle de programme principal.

main()

commence comme pour toute fonction par une accolade

 la seule instruction correspond un appel de fonction qui provoque l'criture sur le terminal. Cette instruction est une demande d'criture d'une chane de caractres ;  la fonction La fonction

main() est termine par une accolade fermante. printf()1 est une fonction2 qui reoit un nombre d'arguments variable. Ces argu-

ments sont transforms en une chane de caractres. Cette transformation fait appel une notion de format. Comme nous le verrons plus loin, le format dnit le type de la donne en mmoire et le mode de reprsentation de la donne lorsqu'elle est ache.

4.2 Lire et crire


Une fonction caractres.

scanf()

fait le pendant la fonction

printf().

Elle permet de lire des valeurs

sur le clavier. Le programme 4.1 est un exemple de lecture et d'criture l'cran d'une chane de

Programme 4.1

1 2 3 4 5 6 7 8 9 10

#include <stdio.h> char tt[80]; /* Tableau de 80 caracteres */ int main (int argc, char *argv[]) { printf ("ecrivez une chaine de caracteres : "); scanf ("%s", tt); printf ("\nLa chaine entree est : %s\n", tt); return 0; }

Lecture et criture de chane par scanf() et

printf()

Donnes en entre
bonjour

Donnes crites sur le fichier standard de sortie


ecrivez une chaine de caracteres : La chaine entree est : bonjour

Ce programme ne dcrit toujours pas les arguments de

main().

Il contient cependant la d-

nition d'une variable globale. Cette variable est un tableau de quatre-vingt caractres destin

1 La

fonction

printf@A

fait

partie de la bibliothque standard. Sur un systme de type UNIX, l'interface qui

dcrit cette fonction est contenue dans le chier

liF.
2 La

stdioFh et le module objet correspondant est contenu dans le chier

Ces chiers sont stocks dans des parties de l'arborescence qui dpendent de l'installation du compilateur

(voir chap. 16). Le chier

stdioFh

est utilis lors de la compilation pour vrier la cohrence d'utilisation des

fonctions. Le module objet est associ au programme lors de l'dition de liens (chap. 1). notion de fonction sera explicite au chapitre 5.

c Christian Bac 1985-2003

CHAPITRE 4.

ELMENTS DE BASE

29

%d %f %c %s

entier dcimal ottant caractre (1 seul) chane de caractres

Tab.

4.1  Conversions usuelles de

printf

et

scanf

recevoir les caractres lus au clavier. Il n'y a toujours pas de variable locale. Les seules instructions sont les appels aux fonctions de lecture et d'criture (scanf() et

printf()).

4.3 Quelques oprations


Les aectations peuvent tre crites comme dans de nombreux autres langages informatiques. En voici quelques exemples :

a a a a

= b + c ; = b * c ; = b / c ; = b - c ;

4.4 Plus sur printf() et scanf()


Les fonctions

printf() et scanf() transforment des objets d'une reprsentation partir d'une

chane de caractres (vision humaine) en une reprsentation manipulable par la machine (vision machine), et vice et versa. Pour raliser ces transformations ces fonctions sont guides par des formats qui dcrivent le type des objets manipuls (vision interne) et la reprsentation en chane de caractres cible (vision externe). Par exemple, un format du type en base 16 (hexadcimal).

%x

signie d'une part que la

variable est du type entier et d'autre part que la chane de caractres qui la reprsente est exprime

Pour

printf(), scanf(),

un format est une chane de caractres dans laquelle sont

insrs les caractres reprsentant la ou les variables crire. Pour un format est une chane de caractres qui dcrit

la ou les variables lire. Pour chaque variable, un type de conversion est spci. Ce type de conversion est dcrit par les caractres qui suivent le caractre %.
Les types de conversion les plus usuels sont donns dans la table4.1. Dans une premire approche de

scanf(),

nous considrons qu'il ne faut mettre que des types

de conversion dans le format de lecture. Le lecteur curieux peut se reporter la section 16.5. Le tableau 4.2 donne un rsum des dclarations de variables et des formats ncessaires leurs manipulations pour Le

printf

et

scanf.

&

est un oprateur du langage C dont nous parlons dans la section 5.1. Cet oprateur doit

tre mis devant le nom de la variable, dans les formats destins la fonction tableau de caractres.

scanf,

comme le

montre le tableau 4.2, pour les variables dont nous avons dj parl sauf pour les variables du type

Les exemples de lecture d'une chane de caractres montrent que l'adresse du premier lment d'un tableau correspond au nom de tableau, nous en reparlerons dans le chapitre 10. c Christian Bac 1985-2003

30

4.4.

PLUS SUR

PRINTF()

ET

SCANF()

dclaration

int i ; int i ; int i ; unsigned int i ; short j ; short j ; short j ; unsigned short j ; long k ; long k ; long k ; unsigned long k ; float l ; float l ; float l ; double m ; double m ; double m ; long double n ; long double n ; long double n ; char o ; char p[10] ;

lecture

scanf("%d",&i) ; scanf("%o",&i) ; scanf("%x",&i) ; scanf("%u",&i) ; scanf("%hd",&j) ; scanf("%ho",&j) ; scanf("%hx",&j) ; scanf("%hu",&j) ; scanf("%ld",&k) ; scanf("%lo",&k) ; scanf("%lx",&k) ; scanf("%lu",&k) ; scanf("%f",&l) ; scanf("%e",&l) ; scanf("%lf",&m) ; scanf("%le"&m) ; scanf("%Lf"&n) ; scanf("%Le"&n) ; scanf("%c",&o) ; scanf("%s",p) ; scanf("%s",&p[0]) ;

criture

printf("%d",i) ; printf("%o",i) ; printf("%x",i) ; printf("%u",i) ; printf("%d",j) ; printf("%o",j) ; printf("%x",j) ; printf("%u",j) ; printf("%ld",k) ; printf("%lo",k) ; printf("%lx",k) ; printf("%lu",k) ; printf("%f",l) ; printf("%e",l) ; printf("%g",l) ; printf("%f",m) ; printf("%e",m) ; printf("%g",m) ; printf("%Lf",n) ; printf("%Le",n) ; printf("%Lg",n) ; printf("%c",o) ; printf("%s",p) ; printf
et

format externe
dcimal octal hexadcimal dcimal dcimal octal hexadcimal dcimal dcimal octal hexadcimal dcimal point dcimal exponentielle la plus courte des deux point dcimal exponentielle la plus courte point dcimal exponentielle la plus courte caractre chane de caractres

Tab.

4.2  Exemples de

scanf

c Christian Bac 1985-2003

CHAPITRE 4.

ELMENTS DE BASE

31

Le programme 4.2, montre qu'il est possible de faire l'criture ou la lecture de plusieurs variables en utilisant une seule chane de caractres contenant plusieurs descriptions de formats.

Programme 4.2

1 2 3 4 5 6 7 8 9 10 11 12

scanf() #include <stdio.h> int main (int argc, char *argv[]) { int i = 10; float l = 3.14159; char p[50] = "Bonjour"; printf ("%d bonjour %f %s\n", i, l, p); scanf ("%d%f%s", &i, &l, p); printf ("Apres lecture au clavier : %d %f %s\n", i, l, p); return 0; }

Lectures multiples avec

Donnes en entre
23 6.55957 salut

Donnes crites sur le fichier standard de sortie


10 bonjour 3.141590 Bonjour Apres lecture au clavier : 23 6.559570 salut

4.5 Exercices sur printf() et scanf()


4.5.1 Exercice 1
Raliser un programme dans un chier contenant une fonction suivantes :  crire le caractre 'a' ;  crire la chane de caractres "bonjour" ;  crire l'entier 32567 dans les formats :  dcimal ;  hexadcimal ;  octal ;  non sign ;  crire le ottant 3.1415927 dans les formats suivants :  notation exponentielle ;  notation avec point dcimal ;  variable (g).

main()

qui ralise les critures

4.5.2 Exercice 2
Reprendre l'exercice 1 en sparant chaque impression par un retour chariot.

4.5.3 Exercice 3
Dclarer des variables des types suivants : c Christian Bac 1985-2003

32

4.5.

EXERCICES SUR

PRINTF()

ET

SCANF()

Programme 4.3

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

#include <stdio.h> int main (int argc, char *argv[], char **envp){ /* ecriture de a bonjour 32567 32567 hexa 32567 octal 32567 non signe */ printf("%c", 'a'); printf("%s", "bonjour"); printf("%d", 32567); printf("%x", 32567); printf("%o", 32567); printf("%d", (unsigned) 32567); /* ecriture de pi format e f g */ printf("%e", 3.1415927); printf("%9.7f", 3.1415927); printf("%g", 3.1415927); return 0; }

Suggestion de corrig chapitre 4 exercice 1

Donnes crites sur le fichier standard de sortie


abonjour325677f3777467325673.141593e+003.14159273.14159

 entier ;  caractre ;  ottant ;  chane de caractres ; puis raliser des oprations de lecture an d'aecter ces variables.

4.5.4 Exercice 4
Lire et rcrire les lments de l'exercice 3.

c Christian Bac 1985-2003

CHAPITRE 4.

ELMENTS DE BASE

33

Programme 4.4

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

#include <stdio.h> int main (int argc, char *argv[], char **envp){ /* ecriture de a bonjour 32567 32567 hexa 32567 octal 32567 non signe */ printf("%c\n", 'a'); printf("%s\n", "bonjour"); printf("%d\n", 32567); printf("%x\n", 32567); printf("%o\n", 32567); printf("%d\n", (unsigned) 32567); /* ecriture de pi au format e f g */ printf("%e\n", 3.1415927); printf("%9.7f\n", 3.1415927); printf("%g\n", 3.1415927); return 0; }

Suggestion de corrig chapitre 4 exercice 2

Donnes crites sur le fichier standard de sortie


a bonjour 32567 7f37 77467 32567 3.141593e+00 3.1415927 3.14159

c Christian Bac 1985-2003

34

4.5.

EXERCICES SUR

PRINTF()

ET

SCANF()

Programme 4.5

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

#include <stdio.h> int main (int argc, char *argv[], char **envp){ /* declaration des variables */ int evry; char dassaut; float ille; char io[100]; /* saisie du nombre entier */ printf("entrer un entier\n"); scanf("%d", &evry); /* saisie du caractere */ /* en effacant le caractere blanc ou \r ou \n precedent genant pour %c */ printf("entrer un caractere\n"); scanf(" %c", &dassaut); /* saisie du nombre reel */ printf("entrer un reel\n"); scanf("%f", &ille); /* saisie de la chaine de caracteres */ printf("entrer une chaine de caracteres\n"); scanf("%s", io); return 0; }

Suggestion de corrig chapitre 4 exercice 3

Donnes en entre
126 f 655957e-1 unseulmot possible

Donnes crites sur le fichier standard de sortie


entrer entrer entrer entrer un entier un caractere un reel une chaine de caracteres

c Christian Bac 1985-2003

CHAPITRE 4.

ELMENTS DE BASE

35

Programme 4.6

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

#include <stdio.h> int main(int argc, char *argv[], char **envp){ /* declaration des variables */ int evry; char dassaut; float ille; char io[100]; /* saisie du nombre entier */ printf("entrer un entier\n"); scanf("%d", &evry); /* saisie du caractere */ /* en effacant le caractere blanc (\r ou \n) precedent genant pour %c */ printf("entrer un caractere\n"); scanf(" %c", &dassaut); /* saisie du nombre reel */ printf("entrer un reel\n"); scanf("%f", &ille); /* saisie de la chaine de caracteres */ printf("entrer une chaine de caracteres\n"); scanf("%s", io); /* impression des resultats */ printf("%d\n%c\n%f\n%s\n", evry, dassaut, ille, io); return 0; }

Suggestion de corrig chapitre 4 exercice 4

Donnes en entre
126 f 655957e-1 unseulmot possible

Donnes crites sur le fichier standard de sortie


entrer un entier entrer un caractere entrer un reel entrer une chaine de caracteres 126 f 65595.703125 unseulmot

c Christian Bac 1985-2003

36

4.5.

EXERCICES SUR

PRINTF()

ET

SCANF()

c Christian Bac 1985-2003

Chapitre 5

Oprateurs et expressions
Le langage C est connu pour la richesse de ces oprateurs. Il apporte aussi quelques notions innovantes en matire d'oprateurs. En particulier, le langage C considre l'aectation comme un oprateur normal alors que les langages qui l'ont prcd (par exemple FORTRAN, ADA) la considrent comme une opration privilgie. Cette richesse au niveau des oprateurs permet d'crire des expressions (combinaisons d'oprateurs et d'oprandes) parfois complexes. Les oprateurs sont les lments du langage qui permettent de faire du calcul ou de dnir des relations. Ils servent combiner des variables et des constantes pour raliser des expressions. La classication faite ci-aprs est guide par le nombre d'oprandes mis en cause par l'oprateur et non par l'utilisation des oprateurs.

5.1 Oprateurs un-aires


Un oprateur un-aire agit sur un oprande qui peut tre une constante, une variable, ou une expression. Ainsi, l'oprateur un-aire

permet d'inverser le signe et on peut crire :

-2 o 2 est une constante ; -i o i est une variable ; -(i+2) o i+2 est une expression.
Le tableau 5.1 donne la liste des oprateurs un-aires. Nous allons prendre quelques exemples pour expliquer l'utilisation de base de ces oprateurs sur les variables dcrites dans le programme 5.1.

Oprateur

Utilisation oprateur d'adresse appel aussi de rfrencement oprateur d'indirection ou de drfrencement sur une adresse oprateur de dcrmentation oprateur d'incrmentation oprateur donnant la taille en octet ngation logique moins unaire, inversion du signe plus unaire complment un

& * -++ sizeof ! + ~

Tab.

5.1  Liste des oprateurs unaires

c Christian Bac 1985-2003

38

5.1.

OPRATEURS UN-AIRES

Programme 5.1 Dnitions de variables et d'un pointeur


int var=10, *pint=&var, nvar=0; long f=20L;

Fig.
Le

5.1  Exemple de relation entre pointeur et variable

5.1.1 Oprateur de rfrencement


dont le nom le suit.

& est l'oprateur de rfrencement, il retourne l'adresse en mmoir (rfrence) de la variable &var donne l'adresse en mmoire de la variable var. Cette adresse peut tre pint = &var ;

utilise pour aecter un pointeur ( la condition que le pointeur soit d'un type compatible avec l'adresse de la variable). Comme le montre l'extrait de l'exemple :

5.1.2 Oprateur de drfrencement ou indirection


Le

* est

l'oprateur d'indirection. Il permet d'accder une variable partir d'une adresse (le

plus souvent en utilisant la valeur contenue dans un pointeur). Dans notre programme 5.1, donne la valeur

10,

de mme que

*pint,

puisque

pint

a t initialis avec l'adresse de

*&var var.

5.1.3 Utilisation des & et *


Prenons un exemple d'utilisation des oprateurs d'adresse et d'indirection en supposant que l'espace mmoire associ aux donnes du programme dbute en octets. La gure 5.1 montre l'espace mmoire associ aux dnitions du programme 5.1, et en particulier, l'association entre le pointeur L'instruction est de quatre octets. Nous supposons de plus que la taille d'un pointeur est elle-aussi de quatre

0x20000 et que la taille d'un entier

pint

et la variable

var.

pint = &nvar ;

est traduite dans la gure5.2.

Fig.

5.2  Mise en relation d'un pointeur et d'une variable

c Christian Bac 1985-2003

CHAPITRE 5.

OPRATEURS ET EXPRESSIONS

39

Une fois cette instruction ralise, l'expression cesseur

1 par les oprations suivantes :

*pint = var - 2

se traduit au niveau du pro-

1. mettre la valeur de (R0

@ 0x20000,

var

2. soustraire 2 cette soit (A0

R0 8) ;

R0 R0 10) ; valeur (R0 R0 -2,


dans le registre soit

3. mettre la valeur de

4.

pint dans le registre A0 soit A0 0x20008) ; mettre la valeur qui est dans R0 l'adresse contenue dans le A0, c'est--dire dans var (@ A0 R0, soit 0x20008 8).
@ 0x20004,

registre

Nous reparlerons des relations entre les pointeurs et les variables dans le chapitre 10 sur les tableaux et les pointeurs.

5.1.4 Oprateurs d'incrmentation et de dcrmentation


Les oprateurs

--

et

++

permettent de dcrmenter et d'incrmenter des variables de type

entier. Dans une premire approche, nous pouvons considrer que :

var = var - 1, ce qui implique en partant d'une variable var ayant une 8 que cette variable contient la valeur 7 une fois l'expression calcule l'excution ; var++ est quivalent var = var + 1, ce qui implique en partant de var ayant une valeur de 8 que cette variable contient la valeur 9 la n de l'excution de l'expression.
est quivalent valeur de Il est possible d'utiliser les oprateurs un-aires d'incrmentation et de dcrmentation derrire la variable (postx) ou devant celle-ci variable (prx). Ce qui permet de post-incrmenter, de pr-incrmenter, de post-dcrmenter ou de pr-dcrmenter. Lorsque l'oprateur est prx, l'opration est applique avant que la valeur correspondant l'opration ne soit calcule. Dans le cas o l'opration est post-xe, la valeur de la variable avant l'opration est utilise pour les autres calculs et ensuite l'opration est applique.

var

0.

Prenons comme exemple, deux entiers

et

j,

et initialisons ces deux variables avec la valeur

int i=0, j=0;


Si nous crivons ter

de

puis mettre la valeur de

j = ++i, c'est une pr-incrmentation de la variable i. Cela signie incrmeni dans j. la n de cette opration i vaut 1 et j vaut 1. En

anticipant sur l'oprateur de succession 5.2.5, nous pouvons considrer cette instruction comme quivalente :

i = i+1 , j = i
Si au contraire, nous crivons menter vaut

j = i++, cela signie mettre la valeur de i dans j puis incri de 1. En partant des mmes valeurs, i valant 0 et j valant 0, la n de cette instruction 1 et j vaut 0. Cette opration est quivalente :

j=i, i = i+1, j
1 Cet
exemple suppose un processeur simple ayant des registres internes banaliss appels R0, R1, . . .pour les registres de donnes et A0, A1 pour les registres d'adresses. L'@ est utilis pour signier le contenu de la variable l'adresse.

c Christian Bac 1985-2003

40

5.1.

OPRATEURS UN-AIRES

5.1.5 Oprateur de taille


L'oprateur

sizeof

donne la taille en octets de la variable dont le nom suit. En gardant les

dnitions de variables du programme 5.1 : L'oprateur

sizeof f

donne la valeur

42 .

Dans notre exemple,

sizeof peut aussi donner la taille d'un type, le sizeof f est quivalent sizeof(long).

type doit tre entre parenthses.

Les calculs associs l'oprateur

langage en assembleur, et non lors de l'excution du programme. L'expression lors de la compilation). Le type de la valeur calcule par sizeof est

sizeof sont raliss par le compilateur lors de la traduction du sizeof f est donc

une valeur constante et peut entrer dans la construction d'une expression constante (calculable

size_t

comme nous l'avons vu dans la section

3.4. Ce type est un type synonyme, comme dcrit dans le chapitre 14, il est dni dans le chier

<stddef.h>.

5.1.6 Oprateur de ngation logique


La ngation logique (non logique, logical not) sert inverser une condition en la faisant passer de vrai faux et rciproquement. sinon. De plus, la norme spcie que !0 vaut Dans notre exemple, En langage C, une expression est fausse si la valeur qu'elle retourne est gale

1.

0, elle est vraie

!var

vaut

car

var

est vraie puisque

var

contient

9.

5.1.7 Plus et moins unaires


Le moins un-aire inverse le signe de l'expression qui le suit. Le plus un-aire a t introduit par la norme ; il n'existait pas dans les versions C 72. Il sert ne pas changer le signe de l'expression.

5.1.8 Complment un
L'oprateur

~ donne le complment un de l'expression entire qui le suit. C'est un oprateur

utilis dans les calculs de masquage et nous le considrons comme un oprateur portant sur les bits de l'oprande associ. Si nous gardons l'exemple de notre variable de type entier

var

contenant la valeur

10.

En

0000 0000 0000 0000 0000 0000 0000 1010 et la valeur ~var est quivalente en binaire : 1111 1111 1111 1111 1111 1111 1111 0101 soit la valeur dcimale -11. -1, dont la valeur en binaire est : 1111 1111 1111 1111 1111 1111 1111 1111
complment 2 puisque plus 1.

considrant qu'un entier est reprsent sur 16 bits, cette valeur est quivalente en binaire :

Comme son nom, complment 1, ne l'indique pas la somme des valeurs

var + ~var est gale

Ceci explique pourquoi en rfrence au complment 1, l'inversion de signe est aussi appele

-var est quivalent ~var +1, soit le complment 1 de la valeur de var

2 Un

entier long sur les machines les plus courantes est reprsent sur 32 bits soit 4 octets.

c Christian Bac 1985-2003

CHAPITRE 5.

OPRATEURS ET EXPRESSIONS

41

Type d'oprateurs Arithmtique

Oprateurs

Usage addition, soustraction, multiplication, division, reste de la division entire. et, ou, ou exclusif vers la droite ou vers la gauche infrieur, infrieur ou gal, suprieur, suprieur ou gal gal, non gal et logique, ou logique aectation succession

Masquage Dcalage Relation

Logique Aectation Succession

+ * / % & | ^ >> << < <= > >= == != && || = ,

Tab.

5.2  Liste des oprateurs binaires

5.2 Oprateurs binaires


Le tableau 5.2 donne la liste des oprateurs binaires.

5.2.1 Oprateurs arithmtiques


Le langage C permet l'utilisation des oprateurs de calcul que l'on trouve habituellement dans les autres langages, savoir : l'addition, la soustraction, la multiplication et la division. Il utilise pour cela les symboles respectifs :

+ - * /.

Comme nous avons dj vu les oprateurs un-aires, vous remarquerez l'utilisation contextuelle dans le cas des trois symboles : son nombre d'oprandes. Comme nous le verrons plus loin, le type (au sens type des donnes) de l'opration est dtermin par le type des valeurs sur lesquelles portent l'opration. Les oprations arithmtiques classiques peuvent s'appliquer aux types entiers et dans ce cas elles ont un comportement d'opration entire (en particulier la division). Ces oprations s'appliquent aussi aux types avec partie dcimale et dans ce cas, elles donnent un rsultat avec partie dcimale. Le langage C introduit l'oprateur modulo, not

+ - *.

Le compilateur dtermine la signication de l'oprateur

%, qui permet d'obtenir le reste de la division

entire dtermine par les deux oprandes entiers qui lui sont associs. Par exemple, l'expression

14 % 3

donne la valeur

2.

5.2.2 Oprateurs manipulant les bits


Les oprateurs de masquage et de dcalages sont utiliss pour manipuler les bitsdes variables entires. Ils servent construire des masques de manire tester certains bits dans des variables de type entier (char

short int long). Ces oprations servent stocker des valeurs qui s'expriment
3 dans le systme UNIX est un exemple

dans de petits intervalles. Par exemple, il sut de trois bits pour exprimer une valeur entre 0 et 7. Ainsi, la reprsentation des droits d'accs sur un chier caractristique d'utilisation. Les oprations de niveau bit sont utilises de manire interne par les systmes d'exploitation pour l'interfaage des priphriques. Elles sont aussi beaucoup utilises dans le cadre des rseaux

3 Les

droits sont exprims sur trois bits que l'on appelle communment les bits r(ead) w(rite) et (e)x(ecute).

Les droits sont exprims pour trois populations : le propritaire du chier, le groupe propritaire et les autres. Un quatrime groupe de trois bits (sst) est utilis pour dnir des comportements particuliers.

c Christian Bac 1985-2003

42

5.2. OPRATEURS BINAIRES

o le contenu d'un espace mmoire est souvent dpendant d'informations reprsentes sur peu de bits. Elles permettent aussi de manipuler les images une fois que celles-ci ont t numrises. Les oprateurs qui permettent de manipuler des expressions au niveau bit sont de deux types ceux qui permettent d'extraire une partie des informations contenue dans un oprande (oprateurs de masquage) et ceux qui modient l'information en dplaant les bits vers la droite ou vers la gauche (oprateurs de dcalage).

Oprateurs de masquage
Les trois premiers oprateurs binaires de niveau bit d'une valeur ou bien forcer certains bits un. Pour reprendre l'exemple des droits d'accs sur un chier dans le systme UNIX, considrons que le type de chier et les droits d'accs d'un chier sont contenus dans une variable du type

\& | ^)

servent slectionner une partie

unsigned short,

et voyons comment nous pouvons extraire ou xer certains droits d'accs au

chier correspondant. Dans le programme 5.2, le mode initial est x

0100751 sachant que la partie haute ( gauche

dans la valeur) reprsente le type du chier et les modes spciaux (bits appels sst) et que les neuf autres bits reprsentent les droits d'accs (rwx respectivement pour le propritaire du chier, pour le groupe auquel appartient le chier et pour les autres utilisateurs). La valeur 1. chier

0100751 sert reprsenter un chier en mode normal 010 dans la partie gauche de la valeur ;

2. pas de traitement particulier (bits sst 0) ; 3. lecture criture et excutable pour le propritaire (7 ou 4. lecture et excutable pour le groupe (5 ou 5. excutable pour les autres(1 ou

111) ;

101) ;

001).

Programme 5.2 Utilisation des oprateurs de masquage


1 int var=10, *pint=&var, nvar=0; 2 long f=20L; 3 char tabc[4]="abc";

Voici l'explication des direntes lignes du programme 5.2 :  la ligne 3 met dans la variable

res

 la ligne 4 met

res la partie de mode qui spcie le type de chier, aprs cette instruction 0100000 ; dans res la valeur courante de mode en conservant le type de chier et en
contient la valeur

forant les bits numro 5 et 3 1. Ces bits reprsentent respectivement le droit en criture pour le groupe et le droit en lecture pour les autres. Ainsi, cette instruction met dans la variable

res

la valeur

 la ligne 5 met dans valeur

0100775 ; res la valeur

de

mode

en inversant les droits d'accs en mode criture

pour les trois populations d'utilisateurs. Aprs cette instruction, la variable

100573,

res

contient la

eaant ainsi le droit d'criture pour le propritaire et donnant ce droit au

groupe propritaire du chier et aux autres utilisateurs.

5.2.3 Oprateurs de dcalage


Les oprateurs de dcalage (<< et

>>)

servent manipuler les valeurs contenues dans les va-

riables de type entier en poussant les bits vers la gauche ou la droite. Ces oprateurs servent raliser des tests ou eacer certaines parties d'une variable. Le dcalage peut se faire vers la gauche ou vers la droite. c Christian Bac 1985-2003

CHAPITRE 5.

OPRATEURS ET EXPRESSIONS

43

Le dcalage vers la droite peut tre sign si l'expression est signe, le rsultat est cependant dpendant de l'implantation (ce qui veut dire que pour crire un programme portable il ne faut pas utiliser le dcalage droite sur une valeur ngative). De manire simple (en ne parlant pas des cas de dbordement), un dcalage vers la gauche d'une position revient une multiplication par deux et un dcalage vers la droite correspond une division par deux.

Programme 5.3

1 2 3 4 5 6 7 8 9 10 11 12 13

#include <stdio.h> int main (int argc, char *argv[]) { unsigned short int mode = 0100751; int res = mode << 4; printf ("res = %o\n", res); res = res >> 4; printf ("res = %o\n", res); res = (mode >> 12) << 12; printf ("res = %o\n", res); return 0; }

Utilisation des oprateurs de dcalage

Donnes crites sur le fichier standard de sortie


res = 2017220 res = 100751 res = 100000
Voici quelques explication sur les dnitions et instructions du programme 5.3 :  la ligne 2 met dans

res

la valeur correspondant

mode

dcal gauche de quatre positions,

supprimant ainsi la partie qui spcie le type de chier. Le dcalage vers la gauche a t ralis en insrant des bits la valeur zro sur la droite de la valeur. La variable la n de cette opration la valeur  la ligne 3 remet dans

conservant que les droits d'accs du chier. Cette ligne met dans la variable

000751. res

res sa valeur courante dcale de quatre positions vers la droite, en ne res la valeur

017220 ;

res contient

Vous constatez que nous avons ainsi eac la partie de la valeur qui correspond au

type du chier ;  rciproquement la ligne 4 eace les bits correspondant aux droits d'accs en mettant dans la valeur de met dans la variable

mode avec les douze bits correspondants res la valeur 010000.

aux droits mis zro. Cette ligne

5.2.4 Oprateurs de relation


Les oprateurs de relation servent raliser des tests entre les valeurs de deux expressions. Comme nous le verrons dans le chapitre 6 ces oprateurs sont surtout utiliss l'intrieur des instructions de contrle de ux (tests). Les oprateurs de relation algbrique sont au nombre de six : (<

<= >

>=

==

!=).

Ces

oprateurs peuvent tre utiliss avec des variables de type entier ou des variables ayant une partie dcimale. Notez le double gal pour le test qui est souvent source de confusion avec le simple gal qui dcrit l'aectation. Les deux autres oprateurs de tests (&&

||)

sont appels respectivement le et logique et

le ou logique. Le et logique permet de dcrire qu'une condition constitue de deux parties est satisfaite si et seulement si les deux parties sont satisfaites. c Christian Bac 1985-2003

44

5.2. OPRATEURS BINAIRES

arithmtique masquage dcalage

+= -= *= /= &= |= ^= >>= <<=

%=

Tab.

5.3  Liste des oprateurs binaires d'aectation

Le ou logique permet de dcrire qu'une condition constitue de deux parties est satisfaite ds lors qu'une des deux parties est satisfaite. Ces oprateurs servent donc dcrire des relations logiques du type ncessit de deux conditions (et logique) ou susance d'une des deux conditions (condition ou). Ces oprateurs s'appliquent des expressions que l'on peut considrer comme de type entier et dont la valeur est teste comme pour le non logique savoir une expression est considre comme fausse si la valeur correspondant cette expression est gale 0. Ainsi en langage C, pour tester si une variable de type entier entre deux bornes non strictes

12

et

143

il faut crire :

j contient une j >= 12 && j <= 143.

valeur comprise

De mme, un test pour savoir si un caractre s'crit :

car == 'a' || car == 'A'.

car contient un 'a' en minuscule ou en majuscule

5.2.5 Oprateur binaire d'aectation et de succession


En langage C, l'aectation est un oprateur comme les autres. Ceci permet d'crire des expressions comme :

i = j = k = 1

qui dtermine une aectation multiple.

La virgule, quant elle, sert sparer deux expressions qui sont values successivement. La valeur associe sera la dernire valeur calcule. Une expression comme :

i = (j=2, k=3)

associe

la valeur 3.

5.2.6 Oprateurs d'aectation


Le langage C permet de construire des oprateurs binaires d'aectation partir des oprateurs binaires arithmtiques, des oprateurs de masquage et des oprateurs de dcalage, en les faisant suivre d'un gal (=).

L'association d'un oprateur binaire avec l'oprateur d'aectation donne les oprateurs dcrits dans le tableau 5.3. Le tableau 5.4 donne un exemple d'utilisation de chacun de ces oprateurs et la faon de lire ces direntes expressions. Ce tableau est construit en supposant que le type entier est reprsent sur 32 bits, et que les deux variables

= 5 ;.

et

sont dnies de la manire suivante :

int i = 100,j

i += ( j * 25 + 342 )

La partie droite de l'oprateur peut tre une expression :

i += ( j += j * 25 + 342 ) - 12
 celle de  celle de Soit, si

Ceci permet d'crire des expressions plus complexes :

La dernire expression arithmtique fait plusieurs aectations :

et

j i

avec avec

j + j * 25 + 342 i + j - 12

ont pour valeur 1 avant cette expression,

vaudra 368 aprs et

vaudra 357.

Ce type d'expression est un peu compliqu et rend le programme dicile lire. Ces possibilits complexes oertes en matire d'expressions sont de ce fait peu utilises ou alors soigneusement encadres par des parenthses qui favorisent la comprhension. c Christian Bac 1985-2003

CHAPITRE 5.

OPRATEURS ET EXPRESSIONS

45

expression

rsultat 110 115 110 105 1050 5250 525 105 5

quivalence

lecture ajoute 10 i ajoute j i retranche 5 i retranche j i multiplie i par 10 multiplie i par j divise i par 10 divise i par j i reoit le reste de la division entire de i par 10

oprateurs arithmtiques

i i i i i i i i i

+= += -= -= *= *= /= /= %=

10 j 5 j 10 j 10 j 10 8 8 4

i i i i i i i i i

= = = = = = = = =

i i i i i i i i i

+ + * * / / %

10 j 5 j 10 j 10 j 10

oprateurs de masquage

i &= i |= i ^=

0 8 0x0C 0xC0 0x0C

i = i & 8 i = i | 8 i = i ^ 4 i = i << 4 i = i >> 4

ET de i avec 8 OU de i avec 8 OU exclusif de i avec 4 dcale i gauche de 4 positions dcale i droite de 4 positions

oprateurs de dcalage

i <<= 4 i >>= 4

Tab.

5.4  Exemples d'oprateurs binaires d'aectation

Oprateur ex1 ? ex2 : ex3

Usage Retourne ex2 si ex1 est vrai retourne ex3 si ex1 est faux

Tab.
5.2.7 Oprateur ternaire

5.5  Oprateur ternaire

L'oprateur ternaire met en jeu trois expressions (ex1,ex2,ex3) et permet de contruire une test avec retour de valeur. La premire expression (ex1) joue le rle de condition. Si la condition est vrie, l'valuation de la deuxime expression est ralise et le rsultat de cette expression est propag comme rsultat de l'expression globale. Dans le cas contraire (le test est faux), l'valuation de la troisime expression est ralise et le rsultat de cette expression est propag comme rsultat de l'expression globale. Prenons pour exemple l'expression

a == b ? c : d. b. c
si la valeur contenue dans la Dans le cas contraire, l'expression retourne la valeur

Cette expression retourne la valeur contenue dans la variable variable

est gale celle de la variable

contenue dans la variable L'expression

d.

a >= b ? a : b a

est value de la manire suivante :

1. si la valeur de de

a;

est suprieure ou gale la valeur de

b,

alors l'expression donne la valeur

2. sinon l'expression donne la valeur de Ainsi l'expression

b;
permet de mmoriser dans la variable

max = a >= b ? a : b

maximum des deux valeurs contenues dans les variables

et

b.

max

la valeur

c Christian Bac 1985-2003

46

5.2. OPRATEURS BINAIRES

Classe d'oprateur Parenthsage Appel de fonction Suxes ou Un-aires prxes Changement de type Multiplicatifs Additifs Dcalages Comparaisons galits et bit bit ou exclusif bit bit ou bit bit et logique ou logique Condition Aectations

Oprateur(s)

Associativit de gauche droite de gauche droite

Succession

() () [] -> . ++ -& * + - ~ ! ++  sizeof sizeof() (type) * / % + << >> < <= > >= == != & ^ | && || ?: = += -= *= /= %= &= |= ^= <<= >>= ,

de droite gauche de droite gauche de gauche droite de gauche droite de gauche droite de gauche droite de gauche droite de gauche droite de gauche droite de gauche droite de gauche droite de gauche droite de droite gauche de droite gauche

de gauche droite

Tab.

5.6  Prcdence des oprateurs

5.2.8 Prcdence des oprateurs


Dans l'valuation d'une ligne contenant des oprateurs et des oprandes, le compilateur utilise des ordres de priorit que nous appelons relations de

prcdence.

Cette prcdence dtermine

l'ordre d'association des oprateurs et oprande par le compilateur. Ces rgles de prcdences sont reprsentes par le tableau 5.6, l'encart suivant donne la grille de lecture de ce tableau.

RGLE de prcdence :

La priorit des oprateurs du langage C est dcroissante de haut en bas selon le tableau 5.6. Lorsque deux oprateurs se trouvent dans la mme case du tableau 5.6, la priorit d'valuation d'une ligne de C dans laquelle se trouvent ces oprateurs, est donne par la colonne de droite (associativit), qui dtermine dans quel ordre le compilateur associe, les oprateurs et les oprandes (en commenant par la droite ou la gauche).
Il faut consulter ce tableau pour tre sr de l'ordre d'valuation d'une expression. L'associativit n'est pas la prcdence entre oprateurs d'une mme ligne de ce tableau. C'est la faon dont le compilateur analyse la ligne source en C. C'est l'ordre dans la ligne source qui est important et non l'ordre sur la ligne du tableau. Pour rsumer, cette rgle de prcdence suit l'ordre :  parenthsage ;  oprateurs d'accs, appel de fonction et post incrmentation ou dcrmentation ;  oprateurs un-aires (associativit de droite gauche) ; c Christian Bac 1985-2003

CHAPITRE 5.

OPRATEURS ET EXPRESSIONS

47

 oprateurs binaires (selon le bon sens commun, mez vous des relations oprateurs de test et oprateurs bit bit) ;  oprateur ternaire (associativit de droite gauche) ;  oprateurs binaires d'aectation (associativit de droite gauche) ;  succession.

5.3 Expressions
Une EXPRESSION est :

une suite syntaxiquement correcte d'oprateurs et d'oprandes.


Maintenant que nous avons vu l'ensemble des oprateurs du langage C, nous pouvons dnir de manire rigoureuse dans l'encart ci dessus la notion d'expression. Une expression est donc une suite syntaxiquement cohrente d'oprateurs et d'oprandes. Cette suite doit donc avoir des oprandes cohrents en nombre et en type avec les oprateurs.

Une expression ramne toujours une valeur, mme si la valeur n'est pas utilise. Une expression est fausse si son rsultat est nul. Elle est vraie si son rsultat est non nul.
La table 5.3 dcrit les relations entre expression et utilisation d'une expression dans un test. Prenons la variable

qui est dnie

int i=10; l'expression i

donne la valeur

10

. Cette

valeur peut tre utilise dans un test et est considre comme vraie dans ce cas.

5.4 Instructions
Maintenant que nous connaissons la notion d'expression nous pouvons introduire celle d' Une

instruction est :

instruction.

 soit une instruction simple,  soit un bloc. Une

instruction simple est :

 soit une instruction de contrle (voir chapitre suivant),  soit une expression suivie de  ;.

Une instruction simple est toujours termine par un  ;.


Un

bloc a la structure suivante :

 une accolade ouvrante "{"  une liste de dnitions locales au bloc (optionnelle)  une suite d'instructions  une accolade fermante "}". partir de maintenant, lorsque nous employons le terme manire indirente l'une des trois signications : 1. instruction simple ; 2. ou instruction de contrle de ot ; 3. ou bloc d'instructions. c Christian Bac 1985-2003

instruction,

il peut prendre de

48

5.5. EXERCICES SUR LES OPRATEURS ET LES EXPRESSIONS

5.5 Exercices sur les oprateurs et les expressions


5.5.1 Exercice 1
Dclarer un entier, un pointeur sur entier et un tableau de 10 entiers. 1. Faire crire l'adresse de l'entier. 2. Aecter la valeur 1 l'entier . 3. Faire crire la valeur de l'entier + 1. 4. Faire crire la valeur de l'entier. Mettre 1, 2, 3, 4 dans le tableau et aecter la valeur correspondant l'adresse de dbut du tableau au pointeur. 1. En utilisant l'oprateur de post-incrmentation, faire crire le contenu du pointeur et son incrment, ainsi que le contenu des entiers points par le pointeur et son incrment. 2. Faire crire la taille de l'entier, du pointeur et du tableau. 3. Faire crire la ngation de ce qui est point par le pointeur.

5.5.2 Exercice 2
Dnir deux entiers

et

initialiss avec les valeurs 10 et 3 respectivement.

Faire crire les rsultats de :     

i i i i i

+ * / %

j j j j j

Trouver une faon dirente de calculer vement

i et j.

i % j.

Aecter les valeurs 0x0FF et 0xF0F respecti-

Faire crire en hexadcimal les rsultats de :     

i i i i j

& j | j ^ j << 2 >> 2

5.5.3 Exercice 3
Dnir deux entiers

et

initialiss respectivement avec les valeurs 1 et 2.

Faire crire les rsultats des direntes oprations logiques entre ou, etc.). Noter les dierences eventuelles entre les resultats de :  

et

(galit, ingalit, et,

i && j i || j

et et

i & j i | j

5.5.4 Exercice 4
En faisant crire les rsultats intermdiaires, raliser les oprations suivantes sur un entier initialis 10 :  division par 2  addition avec 3 c Christian Bac 1985-2003

CHAPITRE 5.

OPRATEURS ET EXPRESSIONS

49

 multiplication par 2  aectation du reste de sa propre division par 3  ou avec 10  dcalage de 2 bits vers la gauche  et avec 19  ou exclusif avec 7. NB : Il est possible de raliser ces oprations de deux facons direntes.

5.5.5 Exercice 5 : Operateur ternaire


En utilisant 4 entiers  lit les valeurs de  crit la valeur  crit la valeur  crit la valeur

i, j, k et l, avec k initialis 12 i et j de k si i est nul ; de i + l i est non nul et j est nul de i + j dans les autres cas.

et

8, crire le programme qui :

5.5.6 Exercice 6
En utilisant quatre variables entires  ajouter 1

i, j, k

et

 en une seule expression aecter la valeur 1

l: i, j

et

k.
et incrmente

de quatre manires direntes.

 crire l'expression qui aecte solutions au moins).  crire l'expression qui met :   

le resultat dei

+ j +1

et

de 1 (quatre

3 * i dans i 3 * i + j dans j divise k par 2 logiquement

 divise la nouvelle valeur de la valeur obtenue.

j par celle de k et met dans l la puissance de 2 correspondant

c Christian Bac 1985-2003

50

5.5. EXERCICES SUR LES OPRATEURS ET LES EXPRESSIONS

Programme 5.4

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

#include <stdio.h>

Suggestion de corrig chapitre 5 exercice 1

int i, *pti, tab[10]; int main (int argc, char *argv[], char **envp){ /* ecriture de l'adresse de l'entier */ printf(" Adresse de l'entier : %x \n", &i); /* affectation de l'entier a 1 */ i = 1; /* ecriture de la valeur de l'entier + 1 */ printf(" Valeur de l'entier + 1 : %d\n", i + 1); /* ecriture de a valeur de l'entier */ printf(" Valeur de l'entier : %d\n", i); /* remplissage du tableau */ tab[0] = 1; tab[1] = 2; tab[2] = 3; tab[3] = 4; /* Affectation de l adresse de debut du tableau au pointeur */ pti = tab; /* ecriture du contenu du pointeur et de son increment. */ printf(" Contenu du pointeur : %x \n", pti); printf(" et de son increment : %x \n", pti + 1); /* ecriture du contenu des objets pointes */ printf(" contenu de l'objet pointe par pt : %d \n", *pti); printf(" et par l'increment de pt : %d \n", *++pti); /* ecriture des tailles de l'entier du pointeur et du tableau */ printf(" Taille de l'entier : %d octets \n", sizeof (i)); printf(" Taille du pointeur : %d octets \n", sizeof (pti)); printf(" Taille du tableau : %d octets \n", sizeof (tab)); /* ecriture de la negation de ce qui est pointe par pt */ printf(" Negation de pt : %d \n", !*pti); return 0; }

Donnes crites sur le fichier standard de sortie


Adresse de l'entier : 8049808 Valeur de l'entier + 1 : 2 Valeur de l'entier : 1 Contenu du pointeur : 80497e0 et de son increment : 80497e4 contenu de l'objet pointe par pt : 1 et par l'increment de pt : 2 Taille de l'entier : 4 octets Taille du pointeur : 4 octets Taille du tableau : 40 octets Negation de pt : 0

c Christian Bac 1985-2003

CHAPITRE 5.

OPRATEURS ET EXPRESSIONS

51

Programme 5.5

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

#include <stdio.h>

Suggestion de corrig chapitre 5 exercice 2

int main(int argc, char *argv[], char **envp){ /* Definition des deux entiers initialises a 10 et 3 */ int i = 10, j = 3; /* ecriture du resultat de differentes operations arithmetiques */ printf(" Le resultat de i + j est %d \n", i + j); printf(" Le resultat de i - j est %d \n", i - j); printf(" Le resultat de i * j est %d \n", i * j); printf(" Le resultat de i / j est %d \n", i / j); printf(" Le resultat de i %% j est %d \n", i % j); /* facon differente de calculer i % j */ printf(" calcul different de i %% j : %d \n", i - (j * (i / j))); /* nouvelle affectation de i et de j */ i = 0x0FF; j = 0xF0F; /* ecriture du resultat de differentes operations logiques */ printf(" Le resultat de i & j est %x \n", i & j); printf(" Le resultat de i | j est %x \n", i | j); printf(" Le resultat de i ^ j est %x \n", i ^ j); printf(" Le resultat de i << 2 est %x \n", i << 2); printf(" Le resultat de j >> 2 est %x \n", j >> 2); return 0; }

Donnes crites sur le fichier standard de sortie


Le resultat de i Le resultat de i Le resultat de i Le resultat de i Le resultat de i calcul different Le resultat de i Le resultat de i Le resultat de i Le resultat de i Le resultat de j + j est 13 - j est 7 * j est 30 / j est 3 % j est 1 de i % j : 1 & j est f | j est fff ^ j est ff0 << 2 est 3fc >> 2 est 3c3

c Christian Bac 1985-2003

52

5.5. EXERCICES SUR LES OPRATEURS ET LES EXPRESSIONS

Programme 5.6

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

#include <stdio.h>

Suggestion de corrig chapitre 5 exercice 3

int i, *pti, tab[10]; int main (int argc, char *argv[], char **envp){ int i = 1, j = 2; /* initialisation de deux entiers */ /* ecriture du resultat de differentes operations logiques */ printf(" Resultat de diverses operations logiques avec i = 1 et j = 2\n"); printf(" Le resultat de i & j est %x \n", i & j); printf(" Le resultat de i | j est %x \n", i | j); printf(" Le resultat de i ^ j est %x \n", i ^ j); printf(" Le resultat de ~i est %x \n", ~i); printf(" Le resultat de ~j est %x \n", ~j); printf(" Le resultat de i && j est %x \n", i && j); printf(" Le resultat de i || j est %x \n", i || j); printf(" Le resultat de !i est %x \n", !i); printf(" Le resultat de !j est %x \n", !j); return 0; }

Donnes crites sur le fichier standard de sortie


Resultat de Le resultat Le resultat Le resultat Le resultat Le resultat Le resultat Le resultat Le resultat Le resultat diverses operations logiques avec i = 1 et j = 2 de i & j est 0 de i | j est 3 de i ^ j est 3 de ~i est fffffffe de ~j est fffffffd de i && j est 1 de i || j est 1 de !i est 0 de !j est 0

c Christian Bac 1985-2003

CHAPITRE 5.

OPRATEURS ET EXPRESSIONS

53

Programme 5.7

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

#include <stdio.h> int main (int argc, char *argv[], char **envp){ int i = 10; printf (" Resultat de diverses operations avec i = %d\n\n", i); /* ecriture du resultat de differentes operations */ printf(" Division par 2 %d\n", i /= 2); printf(" Addition avec 3 %d\n", i += 3); printf(" Multiplication par 2 %d\n", i *= 2); printf(" Reste de la division par 3 %d\n", i %= 3); printf(" OU logique avec 10 %d\n", i |= 10); printf(" Shift de 2 a gauche %d\n", i <<= 2); printf(" ET logique avec 19 %d\n", i &= 19); printf(" OU exclusif avec 7 %d\n", i ^= 7); return 0; }

Suggestion de corrig chapitre 5 exercice 4

Donnes crites sur le fichier standard de sortie


Resultat de diverses operations avec i = 10 Division par 2 5 Addition avec 3 8 Multiplication par 2 16 Reste de la division par 3 1 OU logique avec 10 11 Shift de 2 a gauche 44 ET logique avec 19 0 OU exclusif avec 7 7

c Christian Bac 1985-2003

54

5.5. EXERCICES SUR LES OPRATEURS ET LES EXPRESSIONS

Programme 5.8

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

#include <stdio.h> int main(int argc, char *argv[], char **envp){ int i, j, k = 12, l = 8; /* definition de 4 entiers */ /* lecture des valeurs de i et de j */ printf("\n Entrer la valeur de i :"); scanf("%d", &i); printf("\n Entrer la valeur de j :"); scanf("%d", &j); /* ecriture du resultat selon les valeurs de i et de j * si i est nul, impression de la valeur de k * si j est nul, impression de la valeur de i + l * impression de la valeur de i +j dans les autres cas */ printf("\n resultat : %d\n", (!i ? k : (!j ? i + l : i + j))); return 0; }

Suggestion de corrig chapitre 5 exercice 5

Donnes en entre
126 0

Donnes crites sur le fichier standard de sortie


Entrer la valeur de i : Entrer la valeur de j : resultat : 134

c Christian Bac 1985-2003

CHAPITRE 5.

OPRATEURS ET EXPRESSIONS

55

Programme 5.9

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

#include <stdio.h> int main (int argc, char *argv[], char **envp){ int i, j, k, l; /* definition des 4 entiers */ /* affectation des entiers */ i = j = k = 1; /* incrementation de i de 4 manieres differentes */ printf(" premiere solution i++ = %d \n", i++); printf(" deuxieme solution ++i = %d \n", ++i); printf(" troisieme solution i = i + 1 = %d \n", i = i + 1); printf(" quatrieme solution i += 1 = %d \n", i += 1); /* affectation de i + j + 1 a k et incrementation de i et de j */ printf(" resultat apres affectation et incrementation\n"); k = i++ + j++ + 1; /* ou i++ + ++j ou ++i+j++ ou ++i+ ++j -1 */ printf(" valeur de k : %d \n", k); printf(" valeur de i : %d \n", i); printf(" valeur de j : %d \n", j); /* ecriture d'une expression qui realise les operations suivantes : * 3 * i dans i et 3 * i + j dans j * et divise k par 2 logiquement et divise j par k * et affecte a l la puissance 2 correspondant la valeur precedente */ l = l << (j += (i *= 3)) / (k >>= l = 1); printf(" Resultat apres calcul de l'expression \n"); printf(" valeur de i ......... %d \n", i); printf(" valeur de j ......... %d \n", j); printf(" valeur de k ......... %d \n", k); printf(" valeur de l ......... %d \n", l); return 0; }

Suggestion de corrig chapitre 5 exercice 6

Donnes crites sur le fichier standard de sortie


premiere solution i++ = 1 deuxieme solution ++i = 3 troisieme solution i = i + 1 = 4 quatrieme solution i += 1 = 5 resultat apres affectation et incrementation valeur de k : 7 valeur de i : 6 valeur de j : 2 Resultat apres calcul de l'expression valeur de i ......... 18 valeur de j ......... 20 valeur de k ......... 3 valeur de l ......... 64

c Christian Bac 1985-2003

56

5.5. EXERCICES SUR LES OPRATEURS ET LES EXPRESSIONS

c Christian Bac 1985-2003

Chapitre 6

Instructions de contrle
Les instructions de contrle servent controler le droulement de l'enchanement des instructions l'intrieur d'un programme, ces instructions peuvent tre des instructions conditionnelles ou itratives.

6.1 Instructions conditionnelles


Les instructions conditionnelles permettent de raliser des tests, et suivant le rsultat de ces tests, d'excuter des parties de code direntes.

6.1.1 Test
L'oprateur de test se prsente sous les deux formes prsentes dans l'encart suivant :

if( expression ) instruction if( expression ) instruction1 else instruction2

L'expression n'est pas forcment un test qui retourne la valeur 0 ou +1. Ce peut tre un calcul ou une aectation, car, comme nous l'avons dja dit dans la section5.1.6 , il n'y a pas de type boolen, et une expression est vraie si elle ramne un rsultat non nul ; elle est fausse si le rsultat est nul.

if (a == b) int b = 1 ; if (a = b)

Voici quelques exemples de tests en langage C : usuel comme dans tous les autres langages vrai puisque b est gal 1 (donc non nul), attention car cela met la valeur de b dans a vrai si la fonction getchar ne ramne pas vrai si c n'est pas gal 0 sinon faux

int c ; if (c = getchar()) if (c)

'\0'

Les tests sont souvent imbriqus pour tester si une variable contient une valeur. Par exemple l'ensemble de tests dcrit dans le programme 6.1 permet de tester si un nombre est pair ou impair et si il est suprieur 5 ou non. c Christian Bac 1985-2003

58

6.1. INSTRUCTIONS CONDITIONNELLES

Programme 6.1

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

#include <stdio.h> int main (int argc, char *argv[]) { int i; scanf ("%d", &i); if (i == 6 || i == 8) { printf ("le nombre est superieur a 5\n"); printf ("le nombre est pair\n"); } else if (i == 4 || i == 2 || i == 0) printf ("le nombre est pair\n"); else if (i == 7 || i == 9) { printf ("le nombre est superieur a 5\n"); printf ("le nombre est impair\n"); } else if (i == 5 || i == 3 || i == 1) printf ("le nombre est impair\n"); else printf ("ceci n est pas un nombre\n"); return 0; }

Exemple de tests imbriqus

Donnes en entre
5

Donnes crites sur le fichier standard de sortie


le nombre est impair

6.1.2 Table de branchement

Pour viter les imbrications d'instructions de branchement : c'est l'instruction La syntaxe du

switch.

if,

le C possde une instruction qui cre une table

switch

est rsume dans l'encart suivant : c Christian Bac 1985-2003

CHAPITRE 6.

INSTRUCTIONS DE CONTRLE

59

switch

(expression) case value1 :

{
inst 10 inst 11 inst 12

case value2 :

inst 20 inst 21 inst 22

etc. case valueN : inst N0 inst N1 inst N2 default : inst 30 inst 31 inst 32

}
L'excution du

switch case

est ralise selon les tapes suivantes :

1. l'expression est value comme une valeur entire ; 2. les valeurs des sont values comme des constantes entires ;

3. l'excution se fait partir du

case

dont la valeur correspond l'expression. Elle s'excute

en squence jusqu' la rencontre d'une instruction 4. les instructions qui suivent la condition

break ; ;

case n'est gale la valeur retourne par l'expression ;


case
et du

default sont excutes lorsqu'aucune constante des

5. l'ordre des

default

n'est par prdni par le langage mais par les besoins du

programme ; 6. l'excution partir d'un n'est pas rencontr ; 7. plusieurs valeurs de 8. le dernier

case continue sur les instructions des autres case tant qu'un break
peuvent aboutir sur les mmes instructions ;

case

ne pas avoir de surprise lorsqu'un

break est facultatif. Il vaut mieux le laisser pour la cohrence de l'criture, et pour case est ajout.

Les programmes 6.2, 6.3 et 6.4 sont des exemples d'utilisation de tables de sauts. Le premier exemple 6.2 est symbolique : 1. lorsque l'expression

exp

donne une valeur gale

21,

les instructions numrotes 10, 11, 12,

20, 21 et 22 sont excutes ; 2. lorsque l'expression excutes ; 3. dans tous les autres cas, les instructions 30, 31 et 32 sont excutes. L'exemple 6.3 reprend l'exemple prcdent 6.1 ralis avec des tests imbriqus. L'xcution se droule donc de la mme faon, en utilisant la valeur dans l'expression valeur de

exp

donne une valeur gale

12,

les instructions 20, 21 et 22 sont

switch,

c'est--dire la

1. lorsque i est gal 6 ou 8, le programme crit

le nombre est pair ;

le nombre est superieur a 5, puis crit le nombre est pair ; le nombre est superieur a 5, puis crit

2. lorsque i est gal 0, 2 ou 4, le programme crit 3. lorsque i est gal 9 ou 7, le programme crit

le nombre est impair ;

4. lorsque i est gal 1, 3 ou 5, le programme crit 5. dans les autres cas, le programme crit Dans l'exemple 6.4, la slection une lettre, la variable

le nombre est impair ; ceci n'est pas un nombre. incrmente les variables nb_chiffres ou nb_lettres

selon

que le caractre lu au clavier est un chire, ou une lettre. Si le caractre lu n'est ni un chire ni

nb_others

est incrmente. c Christian Bac 1985-2003

60

6.2.

INSTRUCTIONS ITRATIVES

while( expression ) instruction

Tab.

6.1  Syntaxe du

while

Fig.

6.1  Organigramme du

while

6.2 Instructions itratives


Les instructions itratives sont commandes par trois types de boucles :  le  le  le

while for do while

6.2.1
Le

while
while
est dcrite dans la table 6.1.

La syntaxe du

while

rpte l'instruction tant que la valeur de l'expression s'interprte comme vraie (dif-

frente de zro). Il correspond l'organigramme de la gure 6.1. Dans l'exemple 6.5, la fonction

clavier. Nous supposerons que la valeur

getchar() lorsque la n de chier est dtecte sur le clavier (par la frappe du caractre Contrle
D sur un systme de type UNIX par exemple). Nous reparlerons de manire approfondie de

getchar() est une fonction qui lit un seul caractre sur le EOF est connue et correspond ce que retourne la fonction

getchar()

dans la section 16.1.1.

Dans cet exemple 6.5, les caractres sont lus un par un au clavier et sont rangs dans les cases du tableau boucle

tab.

Cet exemple n'est pas scuris en ce sens qu'il n'y a pas de vrication de

dbordement du tableau. Nous verrons (Prog. 6.7) que cet exemple peut tre rcrit l'aide d'une

for

de manire ne pas dborder du tableau.

L'exemple 6.6 correspond la recopie de la chane de caractres contenue dans Le test de n de chane correspond correspond nul ('\0') la n de la chane

tab[i] != '\0'. Ce test fonctionne correctement car le compilateur a mis un octet tab (qui sans cela n'en serait pas une).
c Christian Bac 1985-2003

tab[i] == '\0'

tab dans tab2.

puisque le test de passage dans la boucle

CHAPITRE 6.

INSTRUCTIONS DE CONTRLE

61

for(exp1 ; exp2 ; exp3) inst

est quivalent

exp1 ; while(exp2) { inst exp3 ; } while

Tab.

6.2  Comparaison du

for

et du

Fig.
6.2.2
for
for
La syntaxe du

6.2  Organigramme du

for

est donne dans l'encart suivant.

for( exp1 ; exp2 ; exp3 ) instruction


Le 1.

for s'utilise avec trois expressions, spares par des points virgules, qui peuvent tre vides : l'expression expr1 est ralise une seule fois lors de l'entre dans la boucle, nous l'appellerons
expression d'initialisation ;

2. l'expression

itration, y compris la premire. Si l'expression controle par le 3. l'expression

expr2 prend la valeur vraie l'instruction for est excute, sinon la boucle se termine ; expr3 contrle l'avancement de la boucle. Elle permet de manire gnrale de while

expr2

est la condition d'excution de l'instruction. Elle est teste chaque

calculer la prochaine valeur avec laquelle la condition de passage va tre retestee, elle est excute aprs l'instruction chaque itration avant le nouveau test de passage. Le

for for

est quivalent un

plus une instruction d'initialisation et une instruction de

contrle comme il est montr dans le tableau 6.2. Le correspond l'organigramme 6.2.

Dans le

for

comme dans le

while,

il est remarquer, que le test est plac en tte et donc que

l'instruction n'est pas forcment excute. Voici quelques exemples de boucle 1. 2.

for

for (i = 0 ; i < 10 ; i++) for (i = 0 , j = 10 ; i < j ; i++ , j--)


c Christian Bac 1985-2003

62

6.2.

INSTRUCTIONS ITRATIVES

Fig.
3.

6.3  Organigramme du

do while

for ( ; ; ) inst
qui joue le rle

Le premier exemple correspond une boucle de parcours classique d'un tableau de taille 10. Dans cet exemple, l'expression d'initialisation met la valeur 0 dans la variable d'indice pour parcourrir le tableau ; la condition d'excution se fait en testant si l'indice courant est strictement infrieur la taille du tableau (10), et la progression d'indice se fait par pas de 1 en utilisant l'oprateur d'incrmentation (++).

Le deuxime exemple montre comment avoir plusieurs initialisations et plusieurs expressions dans l'expression d'avancement de la boucle, en utilisant l'oprateur de succession

,.

Le troisime exemple est une convention pour crire une boucle innie. Ce type de boucle innie est utilis lorsque l'instruction qu'elle contrle n'est pas une instruction simple mais plutt un bloc d'instructions dans lequel se trouvent des conditions de sortie de la boucle (voir section 6.3 sur les ruptures de squence). L'exemple 6.7 montre l'utilisation d'une boucle

for pour la lecture d'un ensemble de caractres

au clavier et l'aectation du tableau avec les caractres lus. L'expression de condition d'excution ralise plusieurs actions. Elle commence par vrier qu'il n'y a pas de risque de dbordement du tableau (indice infrieur la taille du tableau). Puis elle ralise la lecture d'un caractre au clavier qu'elle stocke dans la variable

c.

La valeur mise dans la variable

est alors teste pour vrier

que la n de chier n'a pas t atteinte (attention au parenthsage il est indispensable la bonne excution). Si les deux conditions sont runies, la valeur de l'indice est infrieure la taille du tableau et le caractre lu n'est contenu dans la variable

rang.

EOF,

le caractre lu est mis dans l'lment correspondant au rang

6.2.3

do while
do while
est donne dans l'encart suivant :

La syntaxe du

do instruction while( expression ) ;


A l'inverse du du

while, le do while place son test en n d'excution, d'o au moins une excution.

Il ressemble aux REPEAT UNTIL d'ALGOL ou de PASCAL. L'organigramme correspond celui au moins une fois. Dans l'exemple donn dans le programme 6.8, les variables modis de la manire suivante : 1. 2.

while mais avec le test en n plutt qu'en dbut, ce qui assure que l'instruction est ralise
i, n
et le tableau d'entiers

sont

s[0] reoit 4 et i reoit 1 puis n reoit 563 ; n tant alors suprieur 10 la boucle continue ; s[1] reoit 3 et i reoit 2 puis n reoit 56 ; n tant alors suprieur 10 la boucle continue ;
c Christian Bac 1985-2003

CHAPITRE 6.

INSTRUCTIONS DE CONTRLE

63

3.

s[2]

reoit 6 et

reoit 3 puis

reoit

5; n

tant alors infrieur 10 la boucle se termine.

Lorsque la boucle est termine, le tableau d'entier contient les valeurs 4, 3, et 6 respectivement dans les lments de rangs 0, 1 et 2.

6.2.4 Remarques sur les instructions itratives


Comme nous l'avons vu dans la section 5.4, une instruction peut tre une instruction simple ou un bloc. Les direntes boucles peuvent tre imbriques et, comme nous le verrons dans le chapitre 7 sur la programmation structure, il faut s'astreindre une certaine mise en page pour faciliter la lecture du programme.

6.3 Ruptures de squence


Dans le cas o une boucle commande l'excution d'un bloc d'instructions, il peut tre intressant de vouloir sortir de cette boucle alors que la condition de passage est encore valide. Ce type d'opration est appel une rupture de squence. Les ruptures de squence sont utilises lorsque des conditions multiples peuvent conditionner l'excution d'un ensemble d'instructions. Les ruptures de squence sont ralises par quatre instructions qui correspondent leur niveau de travail : 1. 2. 3. 4.

continue break goto return void exit(int status) qui termine l'excution void longjmp(jmp_buf env, int val) qui permet de sauter un point de

Deux appels de fonctions de la bibliothque permettent aussi de modier l'ordre d'excution d'un programme. Il s'agit de l'appel aux fonctions du programme et reprise mis dans le programme.

6.3.1

continue
continue
est utilise en relation avec les boucles. Elle provoque le passage

L'instruction

l'itration suivante de la boucle en sautant la n du bloc. Ce faisant, elle provoque la non excution des instructions qui la suivent l'intrieur du bloc. Prenons le programme 6.9, qui compte le nombre de caractres non blancs rentrs au clavier, et le nombre total de caractres. Les caractres sont considrs comme blancs s'ils sont gaux soit l'espace, la tabulation horizontale, le saut de ligne ou le retour la colonne de numro zro. la n de l'excution : 1. i contient une valeur qui correspond au nombre total de caractres qui ont t taps au clavier ; 2. j contient une valeur qui correspond au nombre de caractres non blancs ; 3. et i-j contient une valeur qui correspond au nombre de caractres blancs.

6.3.2

break
break
dans le

Nous avons dj vu une utilisation du

switch.

Plus gnralement, il permet de

sortir d'un bloc d'instruction associ une instruction rptitive ou alternative controle par les c Christian Bac 1985-2003

64

6.3. RUPTURES DE SQUENCE

Fig.

6.4 

break

et

continue

dans un

for

Fig.
instructions

6.5 

break

et

continue

dans un

while

if, for, un while ou un do while. Il n'est pas aussi gnral qu'en ADA ou en JAVA

puisqu'il ne permet de sortir que d'un niveau d'imbrication. Dans l'exemple 6.10, nous reprenons l'exemple 6.9, de manire crer une boucle qui compte chariot ('\r') est rencontr, le un le nombre de caractres jusqu'au retour chariot en utilisant l'instruction

while

ou un

do while.

break. Lorsque le retour break provoque la sortie de la boucle for. Il en serait de mme avec

Dans l'exemple 6.11, nous reprenons l'exemple 6.5, de manire crer une boucle qui remplit le tableau en vriant qu'il n'y a pas de dbordement de taille. Dans ce cas, nous utilisons le pour sortir de la boucle lorsque la n de chier est rencontre. Les gures 6.4, 6.5 et 6.6 sont des organigrammes qui montre les eets du sur les boucles

break

for, while,

et

do while.

break et du continue

c Christian Bac 1985-2003

CHAPITRE 6.

INSTRUCTIONS DE CONTRLE

65

Fig.
6.3.3 goto
Le

6.6 

break

et

continue

dans un

do while

goto permet d'aller n'importe o l'intrieur d'une fonction. Son utilisation systmatique

nuit la lisibilit des programmes. Il est cependant trs utilis aprs des dtections d'erreur, car il permet de sortir de plusieurs blocs imbriqus. Il est associ une tiquette appele label. Un label est une chane de caractres suivie du double point  :  . Le programme 6.12 est un extrait de la suite de tests du compilateur

gcc. Dans ce programme :

test_goto1() test_goto2() main()


fonction globale

doit retourner 2 si l'argument qui lui est pass est dirent de 0 et 1 sinon. doit retourner 8 si l'argument qui lui est pass est infrieur 10 et 4 sinon.

provoque l'appel de la fonction

test_goto2

test_goto1() successivement avec les valeurs 0 et 1 puis la

avec une valeur infrieure 10 (3) et une valeur suprieure 10 (30).

Les rsultats obtenus par les retours d'appels de fonctions sont cumuls dans la variable

goto_val.

6.3.4

return
return

Nous tudierons de manire plus dtaille les fonctions dans le chapitre 8. L'instruction

provoque la terminaison de l'excution de la fonction dans laquelle elle se trouve et le retour la fonction appelante. Cette instruction peut tre mise tout moment dans le corps d'une fonction ; son excution provoque la n de celle-ci. Cette instruction est appele de manire implicite la n d'une fonction. Le

return

permet de calculer une valeur correspondant au type de sa fonciton. Ce calcul se

fait en valuant l'expression qui suit le retourne la fonction appelante. Lorsque la fonction est de type que retourne la fonction  

return.

L'expression est value et la valeur calcule est

o la fonction est associ un type qui n'est pas

return ; return expression ;

void, le return est utilis sans expression associe, dans le cas void, la valeur calcule par le return est celle contenant le return. Les formes possibles du return sont donc : return dans une
fonction, le premier qui est excut dans le contexte

Il peut y avoir plusieurs

de la fonction provoque : le calcul de la valeur retrouner, la sortie de la fonction, la continuation de l'excution de la fonction appelante. Nous allons crer une fonction (voir prog. 6.13) qui retourne : elle lit une minuscule,

si elle lit un chire,

-1

si elle lit

EOF

et

0 si elle lit une majuscule, 1 -2 dans tous les autres cas.

si

c Christian Bac 1985-2003

66

6.4.

EXERCICES SUR LES INSTRUCTIONS DE CONTRLE

6.4 Exercices sur les instructions de contrle


6.4.1 Exercice 1
Lire 2 entiers

et

j. if

crire celui possdant la plus grande valeur absolue  avec l'instruction  avec l'oprateur ternaire.

6.4.2 Exercice 2
crire un programme qui imprime le type de lettre(voyelle ou consonne) entre au clavier. Remarque : il peut tre judicieux de transformer les majuscules en minuscules.

6.4.3 Exercice 3
A l'aide d'une boucle

for,

lire 10 entiers et les stocker dans un tableau.

Rcrire le contenu du tableau l'aide d'une boucle

while.

6.4.4 Exercice 4
En utilisant une boucle

do while,

transformer l'exercice 2 de faon arrter le traitement

lorsqu'un caractre autre qu'une lettre est entr au clavier.

6.5 Exercices sur les ruptures de squence


6.5.1 Exercice 5
Lire caractre par caractre une ligne entre au clavier (la n de ligne est caracterise par un retour chariot) et la stocker dans un tableau. unique, et en remplacant le retour chariot de n de ligne par le caractre nul('\0'). Rcrire la ligne ainsi transforme par un Transformer cette ligne en remplacant une suite d'espaces ou une tabulation par un espace

printf()

de chane de caractres.

6.5.2 Exercice 6
Cet exercice consiste en la lecture d'un entier, qui est le rang d'une lettre dans l'alphabet, et en l'criture de la lettre correspondant ce rang. Pour cela il faudra :  initialiser un tableau de caractres avec l'alphabet ;  faire une boucle de lecture d'un entier ;  sortir de la boucle lorsque l'entier lu est 100 ;  imprimer la lettre correspondant l'entier lorsque celui-ci est compris entre 1 et 26 ;  dans les autres cas reboucler en lecture.

c Christian Bac 1985-2003

CHAPITRE 6.

INSTRUCTIONS DE CONTRLE

67

Programme 6.2 Exemple de table de sauts


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41

/* Extracted from GCC source code: this code is copyrighted see GCC source * code for copyright license */ extern void ERROR (char *, ...); extern void warning (char *, ...); extern void pedwarn (char *, ...); extern int fflag, lflag, imag, pedantic; void exemple (char *p) { switch (*p++) { case 'f': case 'F': if (fflag) ERROR ("more than one 'f' suffix on floating constant"); fflag = 1; break; case 'l': case 'L': if (lflag) ERROR ("more than one 'l' suffix on floating constant"); lflag = 1; break; case 'i': case 'I': case 'j': case 'J': if (imag) ERROR ("more than one 'i' or 'j' suffix on floating constant"); else if (pedantic) pedwarn ("ISO C forbids imaginary numeric constants"); imag = 1; break; default: ERROR ("invalid suffix on floating constant"); }

c Christian Bac 1985-2003

68

6.5. EXERCICES SUR LES RUPTURES DE SQUENCE

Programme 6.3

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

#include <stdio.h> int main (int argc, char *argv[]) { int i; scanf ("%d", &i); switch (i) { case 6: case 8: printf ("le nombre est superieur a 5\n"); case 0: case 2: case 4: printf ("le nombre est pair\n"); break; default: printf ("ceci n est pas un nombre\n"); break; case 9: case 7: printf ("le nombre est superieur a 5\n"); case 5: case 1: case 3: printf ("le nombre est impair\n"); break; } return 0; }

Exemple de table de sauts

Donnes en entre
5

Donnes crites sur le fichier standard de sortie


le nombre est impair

c Christian Bac 1985-2003

CHAPITRE 6.

INSTRUCTIONS DE CONTRLE

69

Programme 6.4

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

#include <stdio.h> int main (int argc, char *argv[]) { int c, nb_chiffres = 0, nb_lettres = 0, nb_autres = 0; while ((c = getchar ()) != EOF) { switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': nb_chiffres++; break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': /* toutes les valeurs des */ case 'm': /* lettres doivent etre */ case 'n': /* presentes dans les case */ case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': nb_lettres++; break; default: nb_autres++; break; } } printf ("Chiffres lettres et autres sur le fichier d'entree : %d %d %d\n", nb_chiffres, nb_lettres, nb_autres); return 0; }

Exemple de table de sauts

Donnes en entre
The quick brown fox jumped over the lazy dog, 1234567890.

Donnes crites sur le fichier standard de sortie

Chiffres lettres et autres sur le fichier d'entree : 10 35 13

c Christian Bac 1985-2003

70

6.5. EXERCICES SUR LES RUPTURES DE SQUENCE

Programme 6.5

1 2 3 4 5 6 7 8 9 10 11 12

#include <stdio.h> int main (int argc, char *argv[]) { char tab[80]; int c, rang = 0; while ((c = getchar ()) != EOF) tab[rang++] = c; tab[rang]='\0'; printf("Caracteres lus : %s\n",tab); return 0; }

Lecture d'une ligne avec while

Donnes en entre
The quick brown fox jumped over the lazy dog, 1234567890.

Donnes crites sur le fichier standard de sortie

Caracteres lus : The quick brown fox jumped over the lazy dog, 1234567890.

Programme 6.6

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

while #include <stdio.h> int main (int argc, char *argv[]) { char tab[] = "Message initialise"; char tab2[50]; int i = 0; while (tab[i]) { tab2[i] = tab[i]; i++; } tab2[i] = '\0'; printf ("Resultat de la copie de tab : %s \n", tab); printf ("dans tab2 : %s \n", tab2); return 0; }

Recopie d'une chane avec une boucle

Donnes crites sur le fichier standard de sortie


Resultat de la copie de tab : Message initialise dans tab2 : Message initialise

c Christian Bac 1985-2003

CHAPITRE 6.

INSTRUCTIONS DE CONTRLE

71

Programme 6.7

1 2 3 4 5 6 7 8 9 10 11 12

#include <stdio.h> int main (int argc, char *argv[]) { char tab[80]; int rang, c; for (rang = 0; rang < 80 && (c = getchar ()) != EOF; rang++) tab[rang] = c; tab[rang]='\0'; printf ("Contenu du tableau tab apres execution :\n\t%s\n", tab); return 0; }

Lecture d'une ligne avec for

Donnes en entre
The quick brown fox jumped over the lazy dog, 1234567890.

Donnes crites sur le fichier standard de sortie

Contenu du tableau tab apres execution : The quick brown fox jumped over the lazy dog, 1234567890.

Programme 6.8

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

#include <stdio.h> int main (int argc, char *argv[]) { int s[10], i = 0, j=0, n = 5634; do s[i++] = n % 10; while ((n /= 10) > 10); printf("Valeurs des entiers dans s : "); for(j=0;j<i;j++){ printf("%d ",s[j]); } printf("\n"); return 0; }

Dcomposition des puissances de dix d'un nombre avec un do while

Donnes crites sur le fichier standard de sortie


Valeurs des entiers dans s : 4 3 6

c Christian Bac 1985-2003

72

6.5. EXERCICES SUR LES RUPTURES DE SQUENCE

Programme 6.9

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

for #include <stdio.h> int main (int argc, char *argv[]) { int i, j, c; for (i = 0, j = 0; (c = getchar ()) != EOF; i++) { if (c == ' ') continue; if (c == '\t') continue; if (c == '\r') continue; if (c == '\n') continue; j++; } printf ("Caracteres lus : %d dont non blancs %d \n", i, j); return 0; }

Utilisation du continue dans une boucle

Donnes en entre
The quick brown fox jumped over the lazy dog, 1234567890.

Donnes crites sur le fichier standard de sortie


Caracteres lus : 58 dont non blancs 48
Programme 6.10

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

#include <stdio.h> int main (int argc, char *argv[]) { int i, j, c; for (i = j = 0; (c = getchar ()) != EOF; i++) { if (c == '\r') break; if (c == ' ') continue; j++; } printf ("Caracteres lus : %d dont non blancs %d \n", i, j); return 0; }

Utilisation des ruptures de squence dans une boucle for

Donnes en entre
The quick brown fox jumped over the lazy dog, 1234567890.

Donnes crites sur le fichier standard de sortie


Caracteres lus : 58 dont non blancs 49

c Christian Bac 1985-2003

CHAPITRE 6.

INSTRUCTIONS DE CONTRLE

73

Programme 6.11

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

for break #include <stdio.h> int main (int argc, char *argv[]) { char tab[80]; int c, rang; for (rang = 0; rang < 80; rang++) { if ((c = getchar ()) != EOF) tab[rang] = c; else break; } tab[rang]='\0'; printf("Ensemble de caracteres lus :\n %s\n",tab); return 0; }

Lecture d'une ligne avec

et

Donnes en entre
The quick brown fox jumped over the lazy dog, 1234567890.

Donnes crites sur le fichier standard de sortie

Ensemble de caracteres lus : The quick brown fox jumped over the lazy dog, 1234567890.

c Christian Bac 1985-2003

74

6.5. EXERCICES SUR LES RUPTURES DE SQUENCE

Programme 6.12

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38

goto /* From GCC TestSuite this code is copyrighted see GCC source code for * copyright license */ /* Check the use of goto. */ int goto_val;

Utilisation de l'infme

int test_goto1 (int f) { if (f) /* count(2) */ goto lab1; /* count(1) */ return 1; /* count(1) */ lab1: return 2; /* count(1) */ } int test_goto2 (int f) { int i; for (i = 0; i < 10; i++) /* count(15) */ if (i == f) goto lab2; /* count(14) */ return 4; /* count(1) */ lab2: return 8; /* count(1) */ } /* Added code for test not included in GCC test suite */ #include <stdio.h> int main(int argc, char * argv) { printf("Res1 : %d\n",goto_val += test_goto1 (0)); printf("Res2 : %d\n",goto_val += test_goto1 (1)); printf("Res3 : %d\n",goto_val += test_goto2 (3)); printf("Res4 : %d\n",goto_val += test_goto2 (30)); return 0; }

Donnes crites sur le fichier standard de sortie


Res1 Res2 Res3 Res4 : : : : 1 3 11 15

c Christian Bac 1985-2003

CHAPITRE 6.

INSTRUCTIONS DE CONTRLE

75

Programme 6.13 Utilisation de plusieurs return


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 #include <stdio.h> int testc (int c) { switch (c) { case EOF: return -1; case 'A': case case 'F': case case 'K': case case 'P': case case 'U': case case 'Z': return 0; case '0': case case '5': case return 2; case 'a': case case 'f': case case 'k': case case 'p': case case 'u': case case 'z': return 1; default: break; } return -2; }

'B': 'G': 'L': 'Q': 'V':

case case case case case

'C': 'H': 'M': 'R': 'W':

case case case case case

'D': 'I': 'N': 'S': 'X':

case case case case case

'E': 'J': 'O': 'T': 'Y':

'1': case '2': case '3': case '4': '6': case '7': case '8': case '9': 'b': 'g': 'l': 'q': 'v': case case case case case 'c': 'h': 'm': 'r': 'w': case case case case case 'd': 'i': 'n': 's': 'x': case case case case case 'e': 'j': 'o': 't': 'y':

c Christian Bac 1985-2003

76

6.5. EXERCICES SUR LES RUPTURES DE SQUENCE

Programme 6.14

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38

#include <stdio.h> int main(int argc, char *argv[], char **envp){ int i, j; /* definitions de deux entiers */ printf(" Entrer les valeurs de i et de j "); scanf("%d%d", &i, &j); /* lecture des deux entiers */ /* ecriture de l'entier possedant la plus grande valeur * absolue a l'aide de l'instruction if */ if(i == j || i == -j){ printf("\nles deux entiers i (%d) et j (%d) ", i, j); printf("sont egaux en valeur absolue\n"); return 0; } printf("\nle plus grand en valeur absolue de i (%d) et j (%d)", i, j); printf(" est : "); if(i < 0) if(j < 0) if(i > j) printf(" j : %d\n", j); else printf("i : %d\n", i); else if(-i > j) printf("i : %d\n", i); else printf("j : %d\n", j); else if(j < 0) if(i > -j) printf("i : %d\n", i); else printf("j : %d\n", j); else if(i > j) printf("i : %d\n", i); else printf("j : %d\n", j); /* ecriture de l'entier possedant la plus grande valeur * absolue a l'aide de l'operateur ternaire */ printf("Avec l'operateur ternaire\n"); printf("le plus grand en valeur absolue de i (%d) et j (%d)\n", i, j); printf("est : %c \n", (((i < 0 ? -i : i) > (j < 0 ? -j : j)) ? 'i' : 'j')); printf(" dont la valeur est : %d \n", (((i < 0 ? -i : i) > (j < 0 ? -j : j)) ? i : j)); return 0; }

Suggestion de corrig chapitre 6 exercice 1

Donnes en entre
-25 12

Donnes crites sur le fichier standard de sortie


Entrer les valeurs de i et de j le plus grand en valeur absolue de i (-25) et j (12) est : i : -25 Avec l'operateur ternaire le plus grand en valeur absolue de i (-25) et j (12) est : i dont la valeur est : -25

c Christian Bac 1985-2003

CHAPITRE 6.

INSTRUCTIONS DE CONTRLE

77

Programme 6.15

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

#include <stdio.h> int main(int argc, char *argv[], char **envp){ char c; /* definition de la variable */ /* saisie du caractere a analyser */ printf(" Entrer une lettre : "); scanf(" %c", &c); /* transformation des majuscules en minuscules */ if (c >= 'A' && c <= 'Z') c += 'a' - 'A'; /* ecriture du type de lettre */ switch (c){ case 'a': case 'e': case 'i': case 'o': case 'u': case 'y': printf(" la lettre est une voyelle \n"); break; case 'b': case 'c': case 'd': case 'f': case 'g': case 'h': case 'j': case 'k': case 'l': case 'm': case 'n': case 'p': case 'q': case 'r': case 's': case 't': case 'v': case 'w': case 'x': case 'z': printf(" la lettre est une consonne \n\n"); break; default: printf(" pas une lettre !!!\n\n"); break; } return 0; }

Suggestion de corrig chapitre 6 exercice 2

Donnes en entre
R

Donnes crites sur le fichier standard de sortie


Entrer une lettre : la lettre est une consonne

c Christian Bac 1985-2003

78

6.5. EXERCICES SUR LES RUPTURES DE SQUENCE

Programme 6.16

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

#include <stdio.h> int tab[10]; /* definition du tableau */ int main (int argc, char *argv[], char **envp){ int i; int *pt; /* pointeur pour acceder au tableau */ int nbel = 5; /* premiere solution */ /* remplissage du tableau a l'aide d une boucle for */ printf(" entrer les %d entiers : ", nbel); for(i = 0; i < nbel; i++) scanf("%d", &tab[i]); printf("\n"); /* ecriture du tableau avec une boucle while */ i = 0; while(i < nbel) printf(" l'element %d du tableau est %d \n", i, tab[i++]); /* deuxieme solution a l'aide d'un pointeur */ /* remplissage du tableau a l'aide d'une boucle for */ pt = tab; printf(" entrer les %d entiers : ", nbel); for(i = 0; i < nbel; i++) scanf ("%d", pt++); printf("\n"); /* ecriture du tableau */ i = 0; pt = tab; while(pt < &tab[nbel]){ printf(" l'element %d du tableau est %d \n", i, *pt++); i++; } return 0;

Suggestion de corrig chapitre 6 exercice 3

Donnes en entre
1 2 3 4 5 6 7 8 9 10

Donnes crites sur le fichier standard de sortie


entrer les 5 entiers : l'element 1 du tableau l'element 2 du tableau l'element 3 du tableau l'element 4 du tableau l'element 5 du tableau entrer les 5 entiers : l'element 0 du tableau l'element 1 du tableau l'element 2 du tableau l'element 3 du tableau l'element 4 du tableau est est est est est est est est est est 1 2 3 4 5 6 7 8 9 10

c Christian Bac 1985-2003

CHAPITRE 6.

INSTRUCTIONS DE CONTRLE

79

Programme 6.17

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35

#include <stdio.h> int main (int argc, char *argv[], char **envp){ char c; int count = 0; /* saisie du caractere a analyser */ printf(" Entrer une lettre : "); count = scanf(" %c", &c); if (count <= 0) return 0; do{ /* transformation des majuscules en minuscules */ if (c >= 'A' && c <= 'Z') c += 'a' - 'A'; /* ecriture du type de lettre */ switch(c){ case 'a': case 'e': case 'i': case 'o': case 'u': case 'y': printf(" la lettre est une voyelle \n"); break; case 'b': case 'c': case 'd': case 'f': case 'g': case 'h': case 'j': case 'k': case 'l': case 'm': case 'n': case 'p': case 'q': case 'r': case 's': case 't': case 'v': case 'w': case 'x': case 'z': printf(" la lettre est une consonne \n"); break; default: printf(" pas une lettre !!!\n\n"); break; } printf(" Entrer une lettre : "); count = scanf(" %c", &c); }while(count == 1); return 0; }

Suggestion de corrig chapitre 6 exercice 4

Donnes en entre
qwerty

Donnes crites sur le fichier standard de sortie


Entrer Entrer Entrer Entrer Entrer Entrer Entrer une une une une une une une lettre lettre lettre lettre lettre lettre lettre : : : : : : : la la la la la la lettre lettre lettre lettre lettre lettre est est est est est est une une une une une une consonne consonne voyelle consonne consonne voyelle

c Christian Bac 1985-2003

80

6.5. EXERCICES SUR LES RUPTURES DE SQUENCE

Programme 6.18

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39

#include <stdio.h> char tab[100]; /* ligne initiale */ char ntab[100]; /* ligne avec blancs compresses */ int main (int argc, char *argv[], char **envp) { char c; int i = 0; /* indice dans tab */ int j = 0; /* indice dans ntab */ int blk = 0; /* 1 si blanc rencontre 0 sinon */ int s = 0; /* marque de debut de ligne */ /* remplissage du tableau par lecture de la ligne */ printf(" Entrer une chaine avec des tabs et des blancs \n"); while((c = getchar ()) != '\n'){ if (i >= 99) break; tab[i++] = c; } tab[i] = '\0'; /* parcours de tab et passage dans ntab en supprimant */ /* les caracteres inutiles */ i = 0; while((c = tab[i++]) != '\0'){ /* elimination des tabs et des blancs de debut de ligne */ if((c == ' ' || c == '\t') && s == 0) continue; s = 1; /* remplacement de la tabulation par un blanc */ if(c == '\t') c = ' '; /* remplacement de plusieurs blancs par un seul */ if(c == ' ') if(blk != 0) continue; else blk = 1; else blk = 0; ntab[j++] = c; } ntab[j] = '\0'; /* on assure la fin de chaine */ printf("\nAncienne ligne :\n %s\n", tab); printf("Nouvelle ligne :\n %s\n", ntab); return 0; }

Suggestion de corrig chapitre 6 exercice 5

Donnes en entre Donnes crites sur le fichier standard de sortie


Entrer une chaine avec des tabs et des blancs Ancienne ligne : parcours de tab et passage dans ntab en supprimant Nouvelle ligne : parcours de tab et passage dans ntab en supprimant parcours de tab et passage dans ntab en supprimant

c Christian Bac 1985-2003

CHAPITRE 6.

INSTRUCTIONS DE CONTRLE

81

Programme 6.19

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

#include <stdio.h>

Suggestion de corrig chapitre 6 exercice 6

/* Tableau contenant l'alphabet */ char tab[] = "abcdefghijklmnopqrstuvwxyz"; int main(int argc, char *argv[], char **envp){ int i, count; /* boucle de lecture */ while (1){ i = 0; printf("entrer un nombre : "); count = scanf("%d", &i); if(count != 1) break; /* on n'a pas lu un nombre */ if(i == 100) break; /* sortie de la boucle */ if(i < 1 || i > 26) continue; /* nombre n'est pas entre 1 et 26 */ /* ecriture de la lettre correspondante */ printf("\nle nombre %d correspond a la lettre %c \n", i, tab[i - 1]); } printf("\nFini\n"); return 0; }

Donnes en entre
12 4 -2 6 35 26 100

Donnes crites sur le fichier standard de sortie


entrer un le nombre entrer un le nombre entrer un le nombre entrer un le nombre entrer un Fini nombre : 12 correspond a la lettre l nombre : 4 correspond a la lettre d nombre : entrer un nombre : 6 correspond a la lettre f nombre : entrer un nombre : 26 correspond a la lettre z nombre :

c Christian Bac 1985-2003

82

6.5. EXERCICES SUR LES RUPTURES DE SQUENCE

c Christian Bac 1985-2003

Chapitre 7

Programmation structure
La programmation structure est un nom gnrique qui couvre un courant de penses qui s'est dvelopp entre les annes 1965 et 1975. La programmation structure a pour but de faciliter le travail de relecture des programmes et de minimiser le travail de maintenance.

7.1 Historique
L'historique de ce mouvement est peu prs le suivant :  1965 Dijkstra [Dij65] propose la suppression de GOTO dans les langages. Ceci est associ avec les premiers dveloppements d'ALGOL.  1968 Dijkstra [Dij68] propose les 3 structures fondamentales en programmation.  1971 Wirth [Wir71] le pre du langage Pascal crit un article sur la programmation par ranements successifs.  1974 Wirth [Wir74] explicite la manire d'crire un programme bien structur. De nombreux autres articles ont t crits sur ce sujet.

7.2 Ides fondamentales


La premire rgle en programmation structure est de minimiser le nombre de GOTO dans le programme. Cependant la programmation structure ne se caractrise pas par l'absence de GOTO, mais par la prsence de structures dans le programme. Les ides de base sont les suivantes :  La programmation peut se faire en utilisant un nombre rduit de structures de programmes.  La prsentation du programme doit reter la structure du programme.  Les tches doivent tre clates en sous-tches (ranement).  Le ranement doit tre fait en tenant compte des donnes manipules par les tches. En particulier, les donnes manipules par une tche doivent tre dclares prs de la tche.  Chaque sous-tche doit avoir un point d'entre unique et un point de sortie unique. Il y eut une longue polmique sur la dnition d'un point de sortie unique. Les structures fondamentales sont au nombre de quatre 1. 2.

1 :

squence : les instructions sont excutes de manire squentielle. slection : qui reprsente un choix dans le code excuter. La slection peut se prsenter
sous trois formes : 

if else : reprsentant une alternative.


a dmontr que toute structure de programme peut en fait se ramener aux trois premires.

1 Dijkstra

c Christian Bac 1985-2003

84

7.3. LANGAGE C ET PROGRAMMATION STRUCTURE

3.

if orif : permettant de dcrire un choix multiple. case : destin crer des tables de vrit. itration : pour rpter un traitement tant qu'une
  boucles ont t choisies :  la boucle  la boucle

condition est vrie. Deux types de

4.

sortie est destine terminer une sous-tche. Deux types de sortie sont possibles :  escape termine la sous-tche.  cycle permet de sauter les instructions suivantes d'une boucle et de passer au cycle suivant
de cette boucle.

while : qui place le test avant le traitement. until : qui place le test aprs le traitement.

Il est possible de distinguer trois niveaux dans la structuration d'un programme :  la smantique propre au langage et ses restrictions ;  le respect des recommandations au niveau de l'utilisation des structures de programme ;  la prsentation du texte du programme.

7.3 Langage C et programmation structure


Le langage C est apparu en 1972, c'est--dire en pleine priode de rexion sur les langages structurs. Il supporte donc un ensemble de fonctionnalits qui sont directement issues de ce courant de pense. Le langage C n'a cependant pas l'ambition d'obliger les programmeurs respecter un quelconque style de programmation, ilest en eet peu contraignant au niveau de la compilation et il ore peu de restrictions smantiques.

7.3.1 Ambitions du langage C


Le langage C a t conu et ralis pour crire un systme d'exploitation et les logiciels de base de ce systme (interprteur de commande, compilateur, . . .). Pour ce faire, il doit tre capable de faire les mmes choses que l'assembleur. Il est assez peu contraignant car ces concepteurs l'ont cr pour leur propre utilisation, ils ont donc prfr favoriser l'expressivit du langage (d'o la richesse des expressions) que d'viter les erreurs de programmation en multipliant les tests la compilation. Cette approche est dirente de la programmation structure telle que Wirth l'a dcrit. En Pascal, le programmeur travaille sur une machine virtuelle, la machine Pascal. En C, le programmeur peut crire des choses explicites qui sont lies la structure de la machine. Le langage C est assez peu contraignant. Il ore des structures de programme mais il n'oblige pas les utiliser. En particulier, il autorise les entres multiples et les sorties multiples dans les tches. La mise en page est libre, ce qui permet d'crire des programmes dont la mise en page rete la structure. Les programmes sans mise en page sont rapidement illisibles du fait de la richesse de la syntaxe du C.

7.3.2 C et structures fondamentales


Le tableau 7.1 montre que le C propose des structures de programme quivalentes celles recommandes dans la programmation structure.

7.4 Quelques exemples


Nous allons crire chaque fois trois exemples de code permettant de raliser la mme tche :  le premier exemple est crit de manire la moins structure possible.  le deuxime exemple est crit en respectant les structures mais sans mise en page. c Christian Bac 1985-2003

CHAPITRE 7.

PROGRAMMATION STRUCTURE

85

Type

Structures if else

Instruction C correspondante if (expression) instruction else instruction n'existe pas. switch. while(expression) instruction do instruction while(expression) ; for(expression ;expression ;expression) instruction

slection

if orif case while

itration

until

escape sortie cycle

break ou return continue

Tab.
de reter ces structures.

7.1  C et Structures Fondamentales

 le dernier exemple est crit en respectant les structures et avec une mise en page qui tente Nous allons raliser cet exercice avec des tests et une boucles. Sur les systmes de type UNIX, les outils tels que de la mise en page correcte. L'diteur de aussi pour d'autre langages.

cb

ou

indent

peuvent tre utiliss pour

mettre en page du code mal prsent. Ils fournissent un bon point de dpart pour avoir des ides

emacs ralise ce type d'assistance pour le langage C mais

7.4.1 Exemple avec des tests


La tche ralise par l'ensemble de tests que nous allons crire de plusieurs manires direntes, a pour but de dterminer quel entier

ou

a la plus grande valeur absolue.

Le programme 7.1 est crit de manire la moins structure possible. La dicult lors de la lecture de ce programme 7.1 est de trouver le chemin qui arrive sur les tiquettes. Pour la recherche d'erreur dans un code de ce type, il faut dterminer comment le programme est arriv sur une ligne. Le programme 7.2 est crit de manire structure mais sans mise en page. Dans ce cas, il est dicile de savoir quelles conditions ont men une ligne. En particulier il est dlicat de trouver la condition correspondant un

else.

Le programme 7.3 est crit de manire structure avec mise en page. La mise en page fait apparatre de manire plus vidente l'imbrication des Une autre faon claire d'crire du code avec des programme 7.4. Certains programmeurs annotent les accolades ouvrantes et fermantes avec des labels identiant le type de la structure et le numro de cette structure en commentaires. Cette technique est illustre dans le programme 7.5. L'avantage de ces solutions apparat lorsque la condition s'tend sur plusieurs pages d'un terminal. Cela vite de remonter dans le source en cherchant le

if else.

if else imbriqus est de mettre des accolades

et des commentaires pour identier les accolades fermantes. Cette technique est illustre par le

if

correspondant un

else.

Il est possible de raliser la mme tche en utilisant une table de branchement. Dans l'exemple 7.6, le calcul donnant la condition doit tre comment car les direntes valeurs possibles ne sont pas videntes trouver. c Christian Bac 1985-2003

86

7.4. QUELQUES EXEMPLES

7.4.2 Exemple avec une boucle


Nous allons raliser une fonciton qui calcule la longueur d'un chane de caractre (vue comme un tableau dont la fonction ne connait pas la taille), la boucle ralise le parcours du tableau de caractres (tabc) et continue tant que la caractre lu n'est pas le caractre

'\0'.

Le programme 7.7 ralise ce parcours de tableau, il est crit de manire non structure avec des

goto.

Le programme 7.8 ralise ce parcours de tableau, il est crit de manire structure avec un mais la mise en page laisse dsirer.

for

Le programme 7.9 ralise ce parcours de tableau, il est crit de manire structure avec mise en page.

c Christian Bac 1985-2003

CHAPITRE 7.

PROGRAMMATION STRUCTURE

87

Programme 7.1

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34

#include <stdio.h> int main (int argc, char *argv[]) { int i, j; printf ("Veuillez entrer deux valeurs entieres : "); scanf ("%d%d", &i, &j); if (i == j) goto T3; if (i <= 0) goto L1; if (j <= 0) goto L2; if (i > j) goto T2; goto T1; L2:if (i > -j) goto T2; goto T1; L1:if (j <= 0) goto L3; if (-i > j) goto T2; goto T1; L3:if (-i > -j) goto T2; T1:printf (" le plus grand est j : %d\n", j); goto T4; T2:printf (" le plus grand est i : %d\n", i); goto T4; T3:printf (" i et j sont egaux\n"); T4: return 0; }

Ensemble de tests non structur

Donnes en entre
10 12

Donnes crites sur le fichier standard de sortie


Veuillez entrer deux valeurs entieres : le plus grand est j : 12

c Christian Bac 1985-2003

88

7.4. QUELQUES EXEMPLES

Programme 7.2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

#include <stdio.h> int main (int argc, char *argv[]) { int i, j; printf ("Veuillez entrer deux valeurs entieres : "); scanf ("%d%d", &i, &j); if (i == j) printf (" i et j sont egaux\n"); else if (i < 0) if (j < 0) if (-i > -j) printf (" le plus grand est i : %d\n", i); else printf (" le plus grand est j : %d\n", j); else if (-i > j) printf (" le plus grand est i : %d\n", i); else printf (" le plus grand est j : %d\n", j); else if (j < 0) if (i > -j) printf (" le plus grand est i : %d\n", i); else printf (" le plus grand est j : %d\n", j); else if (i > j) printf (" le plus grand est i : %d\n", j); else printf (" le plus grand est j : %d\n", j); return 0; }

Ensemble de tests structur non mis en page

Donnes en entre
10 12

Donnes crites sur le fichier standard de sortie


Veuillez entrer deux valeurs entieres : le plus grand est j : 12

c Christian Bac 1985-2003

CHAPITRE 7.

PROGRAMMATION STRUCTURE

89

Programme 7.3

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

#include <stdio.h> int main (int argc, char *argv[]) { int i, j; printf ("Veuillez entrer deux valeurs entieres : "); scanf ("%d%d", &i, &j); if (i == j) printf (" i et j sont egaux\n"); else if (i < 0) if (j < 0) if (-i > -j) printf ("le plus grand est i : %d\n", i); else printf ("le plus grand est j : %d\n", j); else if (-i > j) printf ("le plus grand est i : %d\n", i); else printf ("le plus grand est j : %d\n", j); else if (j < 0) if (i > -j) printf ("le plus grand est i : %d\n", i); else printf ("le plus grand est j : %d\n", j); else if (i > j) printf ("le plus grand est i : %d\n", i); else printf ("le plus grand est j : %d\n", j); return 0; }

Ensemble de tests structur et mis en page

Donnes en entre
10 12

Donnes crites sur le fichier standard de sortie


Veuillez entrer deux valeurs entieres : le plus grand est j : 12

c Christian Bac 1985-2003

90

7.4. QUELQUES EXEMPLES

Programme 7.4

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

#include <stdio.h> int main (int argc, char *argv[]) { int i, j; printf ("Veuillez entrer deux valeurs entieres : "); scanf ("%d%d", &i, &j); if (i == j) printf (" i et j sont egaux\n"); else{ if (i < 0){ if (j < 0) if (-i > -j) printf ("le plus grand est i : %d\n", i); else printf ("le plus grand est j : %d\n", j); else if (-i > j) printf ("le plus grand est i : %d\n", i); else printf ("le plus grand est j : %d\n", j); }else{ /* i >= 0 */ if (j < 0){ if (i > -j) printf ("le plus grand est i : %d\n", i); else printf ("le plus grand est j : %d\n", j); } /* fin j < 0 */ else{ if (i > j) printf ("le plus grand est i : %d\n", i); else printf ("le plus grand est j : %d\n", j); } /* fin j > 0 */ } /* fin i > 0 */ } /* fin i != j */ return 0; }

Ensemble de tests structur et mis en page avec commentaires

Donnes en entre
10 12

Donnes crites sur le fichier standard de sortie


Veuillez entrer deux valeurs entieres : le plus grand est j : 12

c Christian Bac 1985-2003

CHAPITRE 7.

PROGRAMMATION STRUCTURE

91

Programme 7.5

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

#include <stdio.h> int main (int argc, char *argv[]) { int i, j; printf ("Veuillez entrer deux valeurs entieres : "); scanf ("%d%d", &i, &j); if (i == j) printf (" i et j sont egaux\n"); else { /* ELIF 1 */ if (i < 0) { /* ELIF1.IF1 */ if (j < 0) if (-i > -j) printf (" le plus grand est i : %d\n", i); else printf (" le plus grand est j : %d\n", j); else if (-i > j) printf (" le plus grand est i : %d\n", i); else printf (" le plus grand est j : %d\n", j); } /* fin ELIF 1.IF1 */ else { /* ELIF 1.ELIF1 */ if (j < 0) { if (i > -j) printf (" le plus grand est i : %d\n", i); else printf (" le plus grand est j : %d\n", j); } /* fin j < 0 */ else { if (i > j) printf (" le plus grand est i : %d\n", i); else printf (" le plus grand est j : %d\n", j); } /* fin j > 0 */ } /* fin ELIF1.ELIF1 */ } /* fin ELIF 1 */ return 0; }

Ensemble de tests structur, mis en page et tiquet

Donnes en entre
10 12

Donnes crites sur le fichier standard de sortie


Veuillez entrer deux valeurs entieres : le plus grand est j : 12

c Christian Bac 1985-2003

92

7.4. QUELQUES EXEMPLES

Programme 7.6

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

#include <stdio.h> int main (int argc, char *argv[]) { int i, j; printf ("Veuillez entrer deux valeurs entieres : "); scanf ("%d%d", &i, &j); if (i == j) printf (" i et j sont egaux\n"); else { /* l'expression (i<0) + 2*(j<0)) donne la valeur : */ /* 0 si i>0 et j>0, 1 si i<0 et j>0 */ /* 2 si i>0 et j<0 3 si i<0 et j<0 */ switch ((i < 0) + 2 * (j < 0)) { case 0: if (i > j) printf ("le plus grand est i : %d\n", i); else printf ("le plus grand est j : %d\n", j); break; case 1: if (-i > j) printf ("le plus grand est i : %d\n", i); else printf ("le plus grand est j : %d\n", j); break; case 2: if (i > -j) printf ("le plus grand est i : %d\n", i); else printf ("le plus grand est j : %d\n", j); break; case 3: if (-i > -j) printf ("le plus grand est i : %d\n", i); else printf ("le plus grand est j : %d\n", j); } /* switch */ } /* fin i != j */ return 0; }

Ensemble de tests par table de branchement

Donnes en entre
10 12

Donnes crites sur le fichier standard de sortie


Veuillez entrer deux valeurs entieres : le plus grand est j : 12

c Christian Bac 1985-2003

CHAPITRE 7.

PROGRAMMATION STRUCTURE

93

Programme 7.7 Boucle ralise par des tests et sauts


1 2 3 4 5 6 7 8 9 10 11 12 13 14 int mystrlen (char tabc[]) { int i; i = 0; B1: if (tabc[i] == '\0') goto B2; i = i + 1; if (i < 100) goto B1; B2: return i; }

Programme 7.8 Boucle ralise par un for()


1 2 3 4 5 6 7

int mystrlen (char tabc[]) { int i; for (i = 0; i < 100; i++) if (tabc[i] == '\0') break; return i; }

Programme 7.9 Boucle ralise par un for() et mise en page


1 2 3 4 5 6 7 8 9 int mystrlen (char tabc[]) { int i; for (i = 0; i < 100; i++) if (tabc[i] == '\0') break; return i; }

c Christian Bac 1985-2003

94

7.4. QUELQUES EXEMPLES

c Christian Bac 1985-2003

Chapitre 8

Fonctions
Les fonctions sont des parties de code source qui permettent de raliser le mme type de traitement plusieurs fois et/ou sur des variables direntes. Les mots procdure et fonction sont employs dans le reste de ce chapitre de manire quasi indirente. Une fonction en langage C peut :  modier des donnes globales. Ces donnes sont dans une zone de mmoire qui peut tre modie par le reste du programme. Une fonction peut dans ces conditions raliser plusieurs fois le mme traitement sur un ensemble de variables dni la compilation ;  communiquer avec le reste du programme par une interface. Cette interface est spcie la compilation. L'appel de la fonction correspond un change de donnes travers cette interface, au traitement de ces donnes (dans le corps de fonction), et un retour de rsultat via cette interface. Ainsi, une fonction permet de raliser le mme traitement sur des ensembles de variables dirents.

8.1 Dnition d'une fonction


Lors de leur dnition ou de leur utilisation les fonctions sont distingues des variables par la prsence des contient :  une interface ;  un corps de fonction qui est en fait un bloc d'instructions. L'interface complte d'une fonction contient :  la dclaration du type de retour et du nom de la fonction ;  une parenthse ouvrante ;  la dclaration des types et des noms des paramtres ;

parenthses ouvrantes et fermantes. Une dnition de fonction, voir gure 8.1

Fig.

8.1  Structure d'une fonction c Christian Bac 1985-2003

96

8.2.

RETOUR DE FONCTION

Code C

Explications fonction plus qui retourne un rsultat de type entier et qui accepte deux arguments

int plus(int a,int b) { a = a + b; return a ; } void add(int a,int b,int *c) { *c = a + b; } long push(double X, int Y) {
...

et

de type entier.

fonction et

add

qui ne retourne pas de rsultat

et qui a trois arguments :

et

sont deux entiers

est un pointeur d'entier

cette fonction modie l'entier point par le dernier paramtre fonction et

push

qui retourne un rsultat de type

et qui a deux arguments :

de type

double

long

de type entier

Tab.
 une parenthse fermante.

8.1  Exemples de dnition de fonctions

L'interface d'une fonction peut tre incomplte si elle ne contient pas le nom des paramtres comme nous le verrons dans le prochain chapitre, cette interface est aussi appele signature de la fonction, et est utilises lorsque des fonctions proviennent de dirents chiers sources ou de bibliothques. Le corps de fonction est un bloc, c'est--dire :  une accolade ouvrante ;  des dclarations de variables locales au bloc ;  des instructions ;  une accolade fermante. Le tableau 8.1 donne des exemples de dnitions de fonctions en C.

8.2 Retour de fonction


Toute fonction qui n'est pas de type

void

retourne un rsultat. Le

type de ce rsultat est

celui de la fonction. La gnration du retour de fonction est provoque par l'appel de l'instruction

return

dont la syntaxe est dcrite dans l'encart suivant.

return expression ;

Dans le corps de la fonction, le rsultat est gnr par le

return. L'expression qui suit le return

est value, et la valeur obtenue est retourne. Au niveau de la fonction appelante, le retour de fonction peut tre utilis comme la valeur d'une expression. Si nous prenons le cas de la fonction une variable (dans cet exemple la variable z).

plus() vue dans le tableau 8.1, la valeur du retour de cette fonction peut tre utilise pour aecter int x=12,y=5,z; z = plus(x,y);
Nous pouvons utiliser ce retour de fonction dans toute expression telle que dnie dans le chapitre 5. Ce qui nous permet d'crire par exemple : c Christian Bac 1985-2003

CHAPITRE 8.

FONCTIONS

97

Dnition

Appel

int plus(int a,int b) { a = a + b; return(a) ; }

int main(int argc, char *argv[]) { int x=4,y=6,z ; z = plus(1,23) ; z = plus(x,y) ; }

Tab.
z = z * plus(x,y) ;

8.2  Exemples d'appels de fonctions

8.3 Passage des paramtres


En langage C,

les passages de paramtres se font par valeur, c'est--dire que la fonction

appelante fait une copie de la valeur passe en paramtre et passe cette copie la fonction appele l'intrieur d'une variable cre dans l'espace mmoire gr par la pile d'excution (voir chap. ). Cette variable est accessible de manire interne par la fonction partir de l'argument formel correspondant. Le tableau 8.2 donne deux exemples d'appels la fonction

plus()

dnie dans le tableau 8.1.

8.3.1 Passage de constantes


La gure 8.2 donne des indications sur une vision de l'espace mmoire pendant l'excution des tapes de l'appel de la fonction correspondant la ligne

z = plus(1,23) ;.

la pile contient les valeurs initiales de Comme la variable

tape 1 tape 2

x, y

et

z,

le sommet de pile est juste au dessus de

z.

n'a pas t initialise nous n'en connaissons pas la valeur ; dont les types corres-

les valeurs 1 et 23 sont empiles dans des variables anonymes

pondent aux types de paramtres de la fonction : dans ce cas deux entiers ; la fonction

et du pointeur de contexte courant. connat sous 23 ;

plus() est appele, ce qui se traduit par l'empilement de l'adresse de retour La fonction plus() dispose de deux variables qu'elle

les noms a et b. Ces deux variables sont les copies des valeurs dont nous

avons parl l'tape prcdente. Elles ont donc pour valeurs initiales respectivement 1 et

tape 3 tape 4 tape 5 tape 6

la fonction

plus() modie la valeur de la variable a

en excutant la ligne

a=a+b ;, elle

met donc la valeur 24 dans a ; la fonction se termine en retournant cette valeur 24, cette valeur est stocke dans un

registre du processeur rserv cet eet ; les variables cres par l'appel sont dtruites (l'espace sur la pile est restitu, le pointeur

de pile est remis sa valeur initiale). la valeur stocke dans le registre du processeur est aecte la variable z (correspondant

l'aectation). La vision donne par les schmas de la gure 8.2, de mme que les autres dessins de ce chapitre, est simpliste en ce sens qu'elle considre que les cases mmoire sur la pile font toutes la mme taille et permettent de stocker des adresses ou des entiers. Elle devrait tre rane pour tenir compte de la taille des types mais alors elle deviendrait spcique une architecture. De mme, elle considre que le sommet de pile est au dessus du bas de pile, et que la taille de la pile est susante pour mettre tout nouvel lment. c Christian Bac 1985-2003

98

8.3.

PASSAGE DES PARAMTRES

Fig.

8.2  Pile et passage de constantes

c Christian Bac 1985-2003

CHAPITRE 8.

FONCTIONS

99

Dclaration

Appel

add(int a,int b,int *c) { *c=a+b; }

int main(int argc, char *argv[]) { int x=5,y=7,z; add(x,y,&z); add(43,4,&x); }

Tab.

8.3  Pointeurs et appels de fonctions

8.3.2 Passage de variables


Le deuxime appel la fonction

z = plus(x,y) ;
et

provoque les oprations suivantes avec un

espace mmoire reprsent dans la gure 8.3 :

tape 1

les valeurs des variables

(4 et 6)

sont calcules, ces valeurs sont empiles dans

tape 2 tape 3 tape 4 tape 5

des variables dont les types la fonction

correspondent aux types de paramtres de la fonction ;

plus() plus()

est appele et elle dispose de deux variables qu'elle nomme "a" et

"b". Ces deux variables sont les copies des valeurs de

et

dont nous avons parl l'tape

prcdente. Ces deux variables ont donc pour valeurs initiales 4 et 6 ; la fonction modie la valeur de la variable "a" en y mettant la valeur 10 ;

la fonction se termine en retournant cette valeur 10 ; les variables cres par l'appel sont dtruites.

Ces deux exemples montrent, que la fonction appele peut modier les paramtres (sauf s'ils sont qualis par

const),

mais ces paramtres sont dans son univers local. Les modications des

paramtres formels par une fonction n'ont aucune inuence sur la valeur des paramtres utiliss lors de l'appel. Par exemple, lorsque lors du deuxime appel, la fonction "a" cela ne modie pas la variable "x".

plus() modie la variable

8.4 Utilisation de pointeurs en paramtres


Il est possible, partir d'une fonction, de modier des objets de la fonction appelante. Pour cela, il faut que la fonction appelante passe les adresses de ces objets . Les adresses sont considres comme des pointeurs dans la fonction appele. Comme pour les autres constantes, il y a promotion de constante variable lors du passage des paramtres par valeur. Il est en eet possible d'appeler la fonction rend un pointeur. Le tableau 8.3 est un exemple d'utilisation de la fonction le rsultat de ses calculs.

plus()

avec des constantes et d'utiliser en

interne de cette mme fonction des variables. Dans le cas d'une adresse, la promotion en variable

add() qui accepte comme arguments

deux entiers et une adresse d'entier. Cette fonction utilise le troisime argument pour communiquer

add(x,y,&z);

La gure 8.4, montre les dirents tats de la pile lors de l'excution du premier appel qui modie la variable

5. Lors du deuxime appel

z en lui add(43,4,&x) ; la

aectant la valeur 12 (5+7), dans les tapes 0 variable

est modie et elle prend la valeur 47

(43+4). Seules les tapes premires tapes de cet appel sont reprsentes sur la gure. Ces tapes de 6 8 correspondent l'appel de fonction et l'excution de l'aectation en utilisant le pointeur. Le retour de la fonction appele la fonction appelante n'est pas reprsent. Il sut de reprendre les tapes numrots 4 et 5 en changeant la che qui va du pointeur la variable associe (ici x au lieu de z) et la valeur de la case mmoire correspondante (x doit contenir 47).

1 Vous

trouvez ici l'explication rationnelle de la formule magique qui consiste mettre un "et commercial" devant

les noms de variables lors de l'appel de la fonction cette fonction.

snf@A.

Il faut en eet passer l'adresse de la variable modier

c Christian Bac 1985-2003

100

8.4. UTILISATION DE POINTEURS EN PARAMTRES

Fig.

8.3  Pile et passage de variables

c Christian Bac 1985-2003

CHAPITRE 8.

FONCTIONS

101

Fig.

8.4  Pile et passage de variables avec rfrence

c Christian Bac 1985-2003

102

8.5. CONVERSION DE TYPE LORS DES APPELS

Type du paramtre

Type aprs conversion

char short int long float double

int int int long double double


8.4  Conversions de type un-aire

Tab.

8.5 Conversion de type lors des appels


Le C selon la description de Kernighan et Ritchie dcrivait la faon avec laquelle les variables taient promues lors des appels de fonction. Cette rgle porte d'une part sur les nombres virgule ottante qui sont transfoms en

double, d'autre part sur tout les types entier dont la taille est plus

petite que l'entier naturel. Lors de l'appel d'une fonction, les paramtres subissent les conversions de type un-aire telles que dcrites dans le tableau 8.4. Les plus importantes sont les suivantes :  les paramtres du type  les paramtres du type

char et short sont transforms en int ; float sont transforms en double.

Les conversions de type ayant lieu lors de l'appel d'une fonction sont dcrites dans le tableau 8.4. Les variables ou les constantes des types suivants sont utilises dans une expression, les valeurs de ces variables ou constantes sont transformes en leur quivalent en entier avant de faire les calculs. Ceci permet d'utiliser des caractres, des entiers courts, des champs de bits et des numrations de la mme faon que des entiers. Le principe permet d'utiliser la place d'un entier :  des caractres et des entiers courts signs ou non signs ;  des champs de bits et des numrations signs ou non signs. La norme C99 maintient ce comportement pour des questions de compatibilits si les fonctions n'ont pas d'interface connue avant l'appel. Dans le cas normal (les fonctions ont une interface connue avant leur utilisation) les valeurs des variables sont passes en maintenant leur type.

8.6 Rcursivit
En C, toute fonction peut appeler toute fonction dont elle connat le nom (nous reviendrons sur ces problmes dans le chapitre 9 sur la visibilit). En particulier, elle peut s'appeler elle-mme. Il est donc possible d'crire des fonctions rcursives. Prenons l'exemple le plus connu en matire de rcursivit : la factorielle. Cette fonction factorielle peut s'crire de la manire suivante :

int fac(int n) { if (n == 0) return 1 ; else return n*fac(n-1) ; }


Les limites de cette rcursivit sont imposes par la taille de la pile d'excution, au chargement du programme en mmoire si le systme utilise une gestion de pile statique. Si vous testez cette fonction, vous serez srement limit, non par la taille de la pile, mais par l'espace de valeur d'un entier.

int fac(int n){ return n ? n*fac(n-1) : 1 ; }

Pour montrer la concision du langage, voici une factorielle crite en une seule ligne :

c Christian Bac 1985-2003

CHAPITRE 8.

FONCTIONS

103

8.7 Arguments de la fonction main()


La structure des arguments de la fonction mtres de la fonction

main()

rete la liaison entre le langage C et le

systme d'exploitation, en particulier le systme UNIX. Dans un systme de type UNIX, les paraune des fonctions du type de la manire suivante :

main() sont passs par le shell dans la majorit des cas. Ils sont passs par exec(3). Ces paramtres ont une structure prdnie. Ils sont dcrits

int main(int argc,char *argv[], char *envp[]) Les noms argc, argv et envp sont des noms mnmoniques. Ils signient argument count, argument values et environment pointer.
La fonction

main()

dispose donc toujours de trois paramtres passs par l'environnement

systme. Ces paramtres sont un entier et deux tableaux de pointeurs sur des caractres. La signication de ces arguments est la suivante :

argc argv

contient le nombre d'arguments qui ont t passs lors de l'appel (nombre de mots dans la ligne de commande) ; contient les arguments de la ligne de commande au niveau du dcoups en mots par le

du binaire excutable

shell

shell.

Ces arguments sont

et chaque mot est rfrenc par un pointeur dans le tableau. contenu de la

Il y a toujours au moins un argument qui correspond au nom du binaire excutable appel ;  le nombre de pointeurs valides dans le premier tableau est donn par le variable entire (nombre d'arguments elle-mme. contient les variables d'environnement du

argc) ;

 la chane pointe par la premire entre du tableau

argv contient le nom de la commande

envp

shell au

moment de l'appel du chier excutable.

Contrairement au premier tableau, la taille de ce deuxime tableau n'est pas donne par un nombre de mots valides. La n de ce deuxime tableau est donne par un marqueur. Ce marqueur est un pointeur NULL, c'est--dire, un pointeur qui contient l'adresse 0. Dans ce cas, cette adresse est du type (char

*)

ou

bien encore adresse d'un caractre.

echo essai de passage de parametres

La gure 8.5 donne la vision interne des paramtres issus de la commande :

Les programmes 8.1 et 8.2 donnent deux exemples d'utilisation des arguments du des variables d'environnement, en utilisant l'impression de chane de caractres par utilisant le format

%s

ou en imprimant chaque caractre un--un, en utilisant le

main et printf() en format %c.

8.8 Pointeur de fonction


En langage C, le nom d'une fonction est considr comme une adresse de manire identique au nom d'un tableau. Le nom d'une fonction correspond l'adresse de la premire instruction l'intrieur du code excutable, une fois l'dition de liens ralise.

8.9 tapes d'un appel de fonction


Pour rsumer voyons les tapes ralises lors d'un appel de fonction. Ces tapes sont au nombre de cinq et sont ralises soit par la fonction appelante soit par la fonction appele :

Mise en pile des paramtres


ramtre est

la fonction appelante empile les copies des paramtres. Si le paempile

une constante (entire, ottante ou adresse), le programme excutable

une copie de cette constante et l'on obtient une variable de type compatible. Ceci explique pourquoi vous pouvez passer une constante et manipuler cette constante comme une variable dans la fonction appele. En C ANSI vous avez cependant la possibilit de dire que la fonction considre ses arguments comme constants. c Christian Bac 1985-2003

104

8.9. TAPES D'UN APPEL DE FONCTION

Fig.

8.5  Arguments de

main()

c Christian Bac 1985-2003

CHAPITRE 8.

FONCTIONS

105

Programme 8.1

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

main() #include <stdio.h> int main (int argc, char *argv[],char **envp) { int i; printf("Nous avons %d arguments : \n",argc); for(i=0;i<argc;i++){ printf("argument %d == %s \n",i,argv[i]); } printf("Nous affichons les 5 premires variables d'environnement \n"); printf("mais nous les comptons toutes. \n"); for(i=0; envp[i] ;i++){ if(i<5) printf("Envp[%d] : %s \n",i,envp[i]); } printf("Il y a %d variables d'environnement : \n",i); return 0; }

Affichage des arguments de

Donnes crites sur le fichier standard de sortie


Nous avons 3 arguments : argument 0 == c08e01 argument 1 == c08e01 argument 2 == c08e01.c Nous affichons les 5 premires variables d'environnement mais nous les comptons toutes. Envp[0] : BIBINPUTS=.:/home/chris/Bib:/usr/share/texmf/bibtex/bib Envp[1] : NNTPSERVER=news.int-evry.fr Envp[2] : MANPATH=/usr/X11R6/man:/usr/local/man:/usr/share/man Envp[3] : COURSC=/home/chris/Enseignement/COURS/C Envp[4] : SYSTEME=Linux Il y a 59 variables d'environnement :

Si les paramtres sont des variables, la fonction appelante empile formel peut tre direntes de celle de son argument rel.

une copie constitue

partir de la valeur courante de la variable. Ceci explique pourquoi la valeur d'un argument

Saut la fonction appele


culier, elle

La fonction appelante provoque un saut l'adresse de dbut de la

fonction appele tout en empilant l'adresse de retour.

Prologue dans la fonction appele

la fonction appele prpare son environnement en parti-

positionne son pointeur de contexte dans la pile tout en sauvegardant l'ancien fonction, de l'autre les variables locales la tape est appe-

pointeur de contexte. Ce pointeur de contexte servira pendant toute l'excution de la fonction retrouver d'un cot les arguments de la fonction. Elle fait ensuite grandir la pile de manire pouvoir ranger une copie des registres qu'elle va utiliser et les variables locales qui ne sont pas en registre. Cette ralisation faits par les concepteurs du compilateur. le le prologue de la fonction. Ce prologue dpend du type du processeur et des choix de

La fonction appele s'excute

jusqu' rencontrer un

l'pilogue dans la fonction appele. Lorsque le

return, ce return provoque le passage return est associ une valeur cette valeur

est conserve dans un registre de calcul (qui sert aussi pour valuer les expressions).

pilogue dans la fonction appele

l'pilogue fait le travail inverse du prologue : savoir, il

c Christian Bac 1985-2003

106

8.10.

EXERCICES SUR LES FONCTIONS

restitue le contexte de la fonction appelante au niveau des registres du processeur (sauf les registres scratch dnitions de restaure les registres qu'il avait sauvegards (correspondants aux registres demands par les variables de type register), puis il restaure le contexte de pile en

2 qui contiennent la valeur de retour de la fonction). Pour cela, l'pilogue


reprenant

l'ancienne valeur dans la pile. Enn, il replace le pointeur qu'il avait avant le prologue. Finalement,

de sommet de pile l'adresse

il retourne la fonction appelante en remettant

dans le pointeur d'instruction la valeur qui avait t sauvegarde sur la pile lors de l'appel. L'xcution continue alors dans la fonction appelante.

Rcupration du rsultat et eacement des paramtres


paramtres qu'elle avait empil au dbut

la fonction appelante dpile les

de l'appel et utilise la(es) valeur(s) de retour

de la fonction pour calculer l'expression courante dans laquelle la fonction a t appele.

8.10 Exercices sur les fonctions


8.10.1 Exercice 1
Dnir trois variables crire une fonction crire la fonction

i, j, k

de type entier et de classe globale. qui fait l'addition de

globadd()

et

dans

k. j,
fait appel la fonction

main()

qui ralise la saisie des variables

d'addition puis crit le rsultat contenu dans

k.

et

8.10.2 Exercice 2
Mme exercice que le prcdent mais en utilisant le passage de paramtres et le retour de fonction. Les trois variables

i, j, k

de type entier sont dclares localement dans la fonction

main().

La fonction d'addition est une fonction retournant un entier. Elle accepte deux paramtres entiers (p1 etp2) et retourne la somme de ces deux paramtres. La fonction

main()

saisit les deux variables locales

et

et appelle la fonction d'addition en

rcuprant le rsultat de cette fonction dans la variable locale l'appel de fonction.

k.

Elle crit le contenu de

aprs

8.10.3 Exercice 3
Mme exercice que le prcdent mais en utilisant le passage de paramtres et un pointeur pour modier une variable dans la fonction appelante. Les trois variables La fonction d'addition

(p1 etp2) et un paramtre de type pointeur vers un entier qui sert pour aecter la variable dont la fonction appelante passe l'adresse avec la somme de ces deux premiers paramtres. La fonction

i, j, k de type entier sont declares localement dans la fonction main(). ptadd() est une fonction sans retour. Elle accepte trois paramtres entiers

main()

saisit les deux variables locales

passant l'adresse de la variable locale

k.

et

et appelle la fonction d'addition en

Elle crit le contenu de

aprs l'appel de fonction.

2 Ce

sont les registres les plus utiliss, ils sont considrs par le compilateur comme utilisables pour l'valuation

de chaque ligne de code.

c Christian Bac 1985-2003

CHAPITRE 8.

FONCTIONS

107

Programme 8.2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

main() #include <stdio.h> int main (int argc, char *argv[],char **envp) { int i; register char *ptc; printf("Nous avons %d arguments : \n",argc); for(i=0;i<argc;i++){ printf("argument %d == ",i); for(ptc=argv[i];*ptc;ptc++) printf("%c",*ptc); printf("\n"); } printf("Nous affichons les 5 premires variables d'environnement \n"); printf("mais nous les comptons toutes. \n"); for(i=0; envp[i] ;i++){ if(i<5){ printf("Environnement %d == ",i); for(ptc=envp[i];*ptc;ptc++) printf("%c",*ptc); printf("\n"); } } printf("Il y a %d variables d'environnement : \n",i); return 0; }

Arguments de

caractres un--un

Donnes crites sur le fichier standard de sortie


Nous avons 3 arguments : argument 0 == c08e02 argument 1 == c08e02 argument 2 == c08e02.c Nous affichons les 5 premires variables d'environnement mais nous les comptons toutes. Environnement 0 == BIBINPUTS=.:/home/chris/Bib:/usr/share/texmf/bibtex/bib Environnement 1 == NNTPSERVER=news.int-evry.fr Environnement 2 == MANPATH=/usr/X11R6/man:/usr/local/man:/usr/share/man Environnement 3 == COURSC=/home/chris/Enseignement/COURS/C Environnement 4 == SYSTEME=Linux Il y a 59 variables d'environnement :

c Christian Bac 1985-2003

108

8.10.

EXERCICES SUR LES FONCTIONS

Programme 8.3

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

#include <stdio.h>

Suggestion de corrig chapitre 8 exercice 1

/* declaration des variables globales */ int i; int j; int k; void globadd(){ k = i + j; }

/* fonction addition */

int main(int argc, char *argv[], char **envp){ /* saisie des valeurs */ printf("entrer 1 entier\n"); scanf("%d", &i); printf("entrer un autre entier\n"); scanf("%d", &j); /* appel de add et impression du resultat */ globadd(); printf(" i + j = %d\n", k); return 0; }

Donnes en entre
24 67

Donnes crites sur le fichier standard de sortie


entrer 1 entier entrer un autre entier i + j = 91

c Christian Bac 1985-2003

CHAPITRE 8.

FONCTIONS

109

Programme 8.4

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

#include <stdio.h> /*

Suggestion de corrig chapitre 8 exercice 2


*/

fonction addition

int add(int p1, int p2){ return (p1 + p2); } int main(int argc, char *argv[], char **envp){ /* declarations des variables locales */ int i, j, k; /* saisie des valeurs */ printf("entrer 1 entier :"); scanf("%d", &i); printf("entrer un autre entier :"); scanf("%d", &j); /* appel de add */ k = add (i, j); printf(" i + j = %d\n", k); return 0; }

Donnes en entre
24 67

Donnes crites sur le fichier standard de sortie


entrer 1 entier :entrer un autre entier : i + j = 91

c Christian Bac 1985-2003

110

8.10.

EXERCICES SUR LES FONCTIONS

Programme 8.5

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

#include <stdio.h> /*

Suggestion de corrig chapitre 8 exercice 3


*/

fonction addition

void ptadd(int p1, int p2, int *pti) { *pti = p1 + p2; return; } int main(int argc, char *argv[], char **envp) { /* declarations des variables locales */ int i, j, k; /* saisie des valeurs */ printf("entrer 1 entier :"); scanf("%d", &i); printf("entrer un autre entier :"); scanf("%d", &j); /* appel de add */ ptadd(i, j, &k); printf(" i + j = %d\n", k); return 0; }

Donnes en entre
24 67

Donnes crites sur le fichier standard de sortie


entrer 1 entier :entrer un autre entier : i + j = 91

c Christian Bac 1985-2003

Chapitre 9

Compilations spares
La compilation spare permet de fragmenter un grand programme en des parties qui peuvent tre compiles indpendamment les unes des autres. Dans ce chapitre nous allons voir comment cette possibilit est exploitable en langage C. partir de maintenant, nous appellerons :  

dclaration : une association de type avec un nom de variable ou de fonction (dans ce cas
la dclaration contient aussi le type des arguments de la fonction),

dnition

: une dclaration et si c'est une variable, une demande d'allocation d'espace

pour cette variable, si c'est une fonction la dnition du corps de fonction contenant les instructions associes cette fonction.

9.1 Programme
de chiers destins tre compils sparment.
Comme nous l'avons dj dit dans le chapitre 1, un programme en langage C est un

ensemble

La structure d'un programme, crit en langage C, est rsume dans la gure 9.1.

9.2 Fichier source


Comme le montre schmatiquement la gure 9.2, chaque chier source contient les lments suivants dans un ordre quelconque :  des dclarations de variables et de fonctions externes,  des dnitions de types synonymes ou de modles de structures (voir chapitre 14),  des dnitions de variables

1,

 des dnitions de fonctions,  des directives de pr-compilation et des commentaires. Les directives de pr-compilation et les commentaires sont traits par le pr-processeur. Le compilateur ne voit que les quatre premiers types d'objets. Les chiers inclus par le pr-processeur ne doivent contenir que des dclarations externes ou des dnitions de types et de modles de structures.

1 Ces

dnitions de variables globales sont en fait transformes par l'diteur de liens en des demandes de rser-

vation mmoire raliser lors du dmarrage du programme.

c Christian Bac 1985-2003

112

9.2. FICHIER SOURCE

Fig.

9.1  Du source l'excutable

Fig.

9.2  Survol d'un chier source

c Christian Bac 1985-2003

CHAPITRE 9.

COMPILATIONS SPARES

113

Rgle fondamentale :

Toute variable ou fonction doit tre dclare avant d'tre utilise.

Tab.

9.1  Rgle fondamentale de visibilit

Fig.

9.3  Exemple de visibilit

9.3 Visibilit
La compilation spare des direntes parties d'un programme implique le respect de certaines rgles que nous appellerons et de fonctions). Comme il a t crit dans le chapitre 1, le compilateur ne lit le chier source qu'une seule fois, et du dbut jusqu' la n. Lorsqu'il rencontre l'utilisation d'une variable ou d'une fonction, il doit connatre son type et sa classe d'adresse. Par convention, dans le cas o une fonction n'est pas connue, le compilateur considre qu'elle retourne une valeur de type

Rgles de visibilit. Ces rgles s'appliquent aux noms (de variables

int et il essaye d'infrer le type des paramtres partir de l'appel (les

appels postrieurs devront se conformer ce premier appel). La fonction peut tre dnie plus loin dans le chier. Si l'interface est conforme ce que le compilateur a devin, le compilateur n'met pas de message d'erreur et utilise l'adresse de la fonction pour les appels suivants, mais il ne peut pas modier ce qu'il a dj gnr. La liaison du premier appel avec la fonction est laisse l'diteur de liens. Nous allons nous servir de l'exemple de la gure 9.3 pour continuer expliquer la visibilit des noms. Pour cet exemple, les rgles de visibilit de noms que nous venons d'noncer nous permettent de dire : 1. la fonction f4 peut appeler les fonctions f4, f3, f2, et f1 ; 2. la fonction f3 peut appeler les fonctions f3, f2, et f1 ; 3. la fonction f2 peut appeler la fonction f2, et f1 ; c Christian Bac 1985-2003

114

9.3.

VISIBILIT

4. la fonction f1 ne peut que s'appeler elle-mme ; 5. les fonctions f1, f2, f3, et f4, peuvent appeler des fonctions inconnues, dans ce cas le compilateur utilise la rgle par dfaut et suppose que le rsultat de la fonction appele est un entier.

9.3.1 Espaces de nommage et visibilit


Nous avons dit dans le chapitre sur la gnralit sur la syntaxe et dans la section2.1.2 Une fonction peut utiliser les variables internes qu'elle a dnies et les variables globales qui ont t dnies avant la fonction. Les noms de variables internes masquent les noms de variables globales. Ainsi, dans la gure9.3 :  la dnition de la variable locale dans cette fonction

de type

long

l'intrieur de la fonction

f1()

masque

50

la variable globale de mme nom et de type entier. L'aectation

ralise dans la fonction

f1()

a =

modie la

variable locale de type long et non la variable

globale ;  par contre la modication de type entier ;  de mme l'argument

a = 10

ralise dans la fonction de la fonction

f2()

aecte la variable globale la

de type

float

f3()

masque dans cette fonction

f3()

variable globale de mme nom et de type entier. L'aectation

a = 10 ralise dans la fonction

modie l'argument local de type oat et non la variable globale.

9.3.2 Extension de la visibilit


Pour le moment, nous n'avons pris en compte que les variables dnies dans le module correspondant une compilation. Il est possible de demander au compilateur de manipuler un objet dni dans un autre module, en lui prcisant que l'objet est de classe faire une dclaration et non une dnition de l'objet. Si l'objet est une variable, le compilateur accepte son utilisation et fait les contrles de cohrence sur son type. Il ne propose pas l'diteur de liens de rserver de la place mmoire pour elle. Il lui demande de retrouver la variable dans les autres modules. Ces dclarations se placent aussi bien au niveau global qu' l'intrieur des blocs. Bien entendu, une telle variable doit tre dnie dans un autre chier du programme et tous les chiers doivent tre associs par une dition de liens, sinon cette dernire se termine avec des rfrences non rsolues et le chier binaire excutable n'est pas produit. La gure 9.4 donne un exemple de dnition et de dclaration de variables entre deux modules d'un mme programme. Dans cet exemple :  les variables

extern. Ceci revient donc

et

sont dnies dans le chier

prg1.c.

Ces variables peuvent tre utilises

par les fonctions  la variable

contenues dans ce chier. De plus ces variables sont accessibles partir

des autres modules du programme qui les auront dclares. fonctions dnies dans

a est dclare en tte du chier prg2.c ; elle peut donc tre utilise par toutes les prg2.c. Le compilateur fait la liaison avec cette dclaration lors de l'utilisation de la variable dans les fonctions f2() et f3(). Il demande l'diteur de liens de trouver la variable a. de mme, la variable b est dclare localement dans la fonction f3() et peut tre utilise
par cette fonction. Le compilateur fait les vrications grce aux informations fournies par la dclaration et demande l'diteur de liens de trouver la variable. c Christian Bac 1985-2003

CHAPITRE 9.

COMPILATIONS SPARES

115

Fig.

9.4  Visibilit des variables entre modules

9.4 Prototypes des fonctions


Les rgles de visibilit s'appliquent aux fonctions de la mme manire qu'elles s'appliquent aux variables globales. Il est possible de dclarer une fonction dirent de celui o elle est dnie. La norme ANSI a ajout au langage C la possibilit de dclarer les prototypes des fonctions, appels parfois signatures des fonctions, en incluant les types des arguments dans la ligne de dclaration. Un prototype permet de vrier que les arguments passs une fonction sont corrects en nombre et en type. Ainsi, les interfaces des fonctions que nous avons vues dans le chapitre 8 sont dcrites par les prototypes du programme 9.1. Comme le montrent les lignes 6 et 7 du programme 9.1, pour reprsenter des fonctions ayant des arguments variables en nombre et en type (comme trois points dans la liste des arguments. Pour dcrire le prototype d'une fonction qui n'accepte pas d'argument, on utilise le type dans la liste des arguments comme le montre la dernire ligne du programme 9.1.

extern an de l'utiliser dans un module

printf()

et

scanf())

le langage C utilise

void

Programme 9.1 Exemples de prototypes de fonctions


1 2 3 4 5 6 7 8 extern extern extern extern extern extern extern extern int add (int, int); void add2 (int, int, int *); long push (int, double); int fac (int); main (int, char *[], char *[]); int scanf (char *, ...); int printf (char *, ...); int getchar (void);

c Christian Bac 1985-2003

116

9.5. FONCTIONS EXTERNES

Fig.

9.5  Visibilit des fonctions entre modules

Fig.

9.6  Visibilit des fonctions dans un module

9.5 Fonctions externes


Une fois connues, les fonctions des autres modules peuvent tre utilises. Comme le montre la gure 9.5, si la fonction chier

prg2.c,

f1()

est dnie dans le chier

il faut mettre en dbut de

prg2.c,

prg1.c

le prototype

extern int f1(void) ;.

et que l'on veut l'utiliser dans le

9.6 Fonctions dnies ultrieurement


De mme, pour utiliser une fonction dnie plus loin dans le module, il faut faire une dclaration de cette fonction. Le compilateur fait la mise--jour de la rfrence lorsqu'il rencontre la dnition. Comme le montre la gure 9.6, la dclaration fonction sans en connatre le corps.

extern int f2(void)

permet l'utilisation d'une

9.7 Vrication des prototypes


Dans la premire version du langage, la liste des types d'arguments n'tait pas mise dans le prototype des fonctions, ce qui n'informait pas le compilateur sur le nombre et le type des arguments. Le compilateur ne pouvait donc pas raliser de contrle de cohrence sur le nombre et c Christian Bac 1985-2003

CHAPITRE 9.

COMPILATIONS SPARES

117

le type des arguments passs lors de l'appel. Lorsqu'on travaille avec des vieux chiers sources en langage C, la programmation doit donc tre trs soigne. L'utilitaire

lint, souvent prsent avec la chane de compilation, fait ce genre des vrications.

La normalisation du langage C a introduit de manire complte l'utilisation des prototypes de manire garantir une bonne prise en compte des prototypes.

9.8 Multiples dclarations et dnitions


En fait, en langage C, une dclaration de variable globale qui n'est pas associe avec une initialisation est candidate tre une dnition. Ainsi, il est possible de trouver plusieurs dclarations de variables sans le mot

extern

dans plusieurs modules et mme dans un seul module. Le compi-

lateur demande l'diteur de liens de rsoudre les conits potentiels. Il ne peut bien sr n'y avoir qu'une seule initialisation qui transforme la dclaration candidate en dnition. Pour des questions de lisibilit, les compilateurs acceptent donc les dnitions candidates de variables, ils acceptent ces dnitions de manire multiple si le type est identique. Le compilateur ne fait la demande de rservation d'espace qu'une seule fois. Il considre les dnitions ultrieures comme des dclarations. Cette facilit permet au programmeur de mettre des dclarations de variables prs des endroits o elles sont manipules. L'exemple 9.2 montre l'utilisation de plusieurs dclarations candidates devenir une dnition d'une mme variable. Dans cet exemple les deux fonctions maninpulent la mme variable

a.

plusplus()

et

moinsmoins()

Programme 9.2 Dclarations candidates multiple d'une variable


1 2 3 4 5 int a; void plusplus(void){a++;}

int a; void moinsmoins(void){a--;}

Nous recommandons :  d'viter les dclarations candidates la dnition,  de toujours associer la dnition avec une initialisation,  d'utiliser le mot

extern

devant les dclarations.

Le programme 9.3 reprend notre programme 9.2 en tant conforme ces recommandations.

Programme 9.3 Dclaration explicite et dclaration candidate d'une variable


1 2 3 4 5 extern int a; void plusplus(void){a++;}

int a=0; void moinsmoins(void){a--;}

int a ; void f1(void){ a= a+1 ; extern int a ; void f4(void){ a -- ;}

} }

f1 et f4 manipulent la mme variable a

c Christian Bac 1985-2003

118

9.8. MULTIPLES DCLARATIONS ET DFINITIONS

Fig.

9.7  Utilisation de chier d'inclusion

9.8.1 Fichiers d'inclusion


Les chiers d'inclusion sont destins contenir des dclarations  types non prdnis,  modles et noms de structures,  types et noms de variables,  prototypes de fonctions. Les chiers d'inclusion contiennent les dclarations des variables et fonctions utilises par plusieurs modules. La gure 9.7 est un exemple dans lequel :  le chier

2 d'objets des types suivants :

defs.h contient les dclarations des variables globales et des fonctions qui peuvent prg1.c ; a
et

tre utilises dans plusieurs chiers sources participant au programme ;  les variables qui peuvent tre utilises par plusieurs modules sont dans le module  les fonctions utilisables sont dnie dans le module  le module fonction fonction

qui sont dnies et

prg2.c, demande l'inclusion du chier defs.h qui fournit la f3() lors de la compilation. Ceci permet l'utilisation de cette f2() sans ambigut.

f1() prg2.c ;

qui est dnie dans le module

prg1.c

f3()

qui est

dclaration de la fonction dans la

2 Ce

sont des dclarations et non des dnitions. En eet, les chiers d'inclusion sont associs plusieurs chiers

source et si ces chiers contiennent des dnitions, les variables risquent d'tre dnies plusieurs fois.

c Christian Bac 1985-2003

CHAPITRE 9.

COMPILATIONS SPARES

119

Fig.

9.8  Rduction de visibilit

9.8.2 Rduction de la visibilit


Dans un environnement qui permet plusieurs programmeurs de constituer un seul programme, il est intressant d'avoir un mcanisme qui permet de restreindre l'accs de variables ou de fonctions pour viter les eets de bords et permettre une meilleure utilisation des interfaces entre modules sans permettre l'accs aux fonctionnement interne d'un module. En langage C, le prdicat

autres chiers du programme. Une variable de type

static permet de masquer des noms de donnes ou de fonctions aux global static n'est visible que du module

qui la dclare. Elle n'est accessible qu'aux fonctions dnies aprs elle dans le mme chier. Ceci permet, entre autre, de manipuler des donnes qui ont le mme nom dans plusieurs chiers avec des dnitions direntes dans chacun d'entre-eux. Comme le montre la gure 9.8, une fonction peut aussi tre dclare

static, elle sera alors in-

accessible aux fonctions des autres chiers constituant le programme. Une tentative de dclaration

extern

d'une variable ou d'une fonction statique est inecace.

9.8.3 Variables locales rmanentes


Pendant l'excution, les variables locales sont normalement cres l'entre du bloc dans lequel elles sont dnies. Les variables

locales

un bloc, appeles galement variables automatiques,

sont naturellement invisibles de l'extrieur de la fonction. c Christian Bac 1985-2003

120

9.8. MULTIPLES DCLARATIONS ET DFINITIONS

Fig.

9.9  Variables locales statiques

Le langage C donne la possibilit d'avoir des variables internes un bloc dont la dure de vie est la mme que celle des variables globales. Le prdicat

static

appliqu une variable locale,

modie le lieu o cette variable est implante ; elle est, alors, mise avec les variables globales. Son nom reste invisible l'extrieur de la fonction. Le prdicat static peut tre utilis pour des structures ou des tableaux de grande taille internes une fonction. Ceci permet de minimiser le surcot caus par la cration et la destruction de l'espace mmoire pour stocker ces variables de grande taille l'entre et la sortie de la fonction. L'isolation de la variable est smantique, son nom n'tant pas connu du reste du programme. Cette isolation n'est pas totale en eet :  si une fonction retourne un pointeur contenant l'adresse d'une variable peut tre utilis par le reste du programme. Le contrle statique, celui-ci d'accs la variable est vri variable

la compilation mais non l'excution. Une variable locale statique peut aussi tre modie par des eets de bord (par exemple un dbordement de tableau peut craser la statique locale que l'diteur de lien a plac aprs le tableau) ;  la dure de vie d'une variable locale statique est la mme que celle des variables globales. A chaque appel, une fonction retrouve la valeur d'une variable locale statique qu'elle a modie lors des appels prcdents. Nous pouvons donc avoir une variable interne une fonction qui compte le nombre d'appels cette fonction.  l'initialisation d'une variable statique interne une fonction non l'entre dans la fonction. Lorsque le programme de la gure 9.9 s'excute la variable entire successivement les valeurs : 1,2,3,4,5,6,7,8,9 et la variable valeurs : 1,11,21,31,41,51,61,71,81,91. est faite la compilation, et

de type global prend

locale f1 prend successivement les

9.8.4 Travailler en groupe


La compilation spare permet le dcoupage d'un programme en parties dveloppes sparment par des programmeurs, c'est un dbut mais pour permettre un travail ecace de groupe il faut quelques rgles supplmentaires. Le projet GNU est un bon exemple quant- l'utilisation de ce type de rgles, vous trouverez les rgles utilises par les groupes de programmeurs de ce projet l'adresse suivante :

http ://www.gnu.org/prep/standards.

c Christian Bac 1985-2003

CHAPITRE 9.

COMPILATIONS SPARES

121

9.9 Exercices sur les fonctions et la visibilit des variables


9.9.1 Exercice 1 : simulation d'un ascenseur
Le programme que vous devez raliser simule une partie du fonctionnement d'un ascenseur. Il n'est pas dans ses buts de simuler compltement un fonctionnement d'ascenseur. L'immeuble dans lequel se trouve cet ascenseur est constitu de dix tages et trois sous-sols. L'ascenseur dessert ces tages et reconnait les tages en sous-sol car ils correspondent des chires ngatifs. Au dpart, l'ascenseur se situe l'tage 0. Il y a trois tapes fondamentales dans le fonctionnement de l'ascenseur :  l'appel de l'ascenseur un tage ;  l'entre dans l'ascenseur suivie de la slection de l'tage dsir ;  le dplacement de l'ascenseur qui peut se faire entre l'appel et l'entre ou entre la selection et la descente. La marche de l'ascenseur que vous devez raliser consiste en :  demander le numro de l'tage ou` l'on appelle l'ascenseur et le lire ;  acher le dplacement de l'ascenseur tage par tage avec une temporisation de 2 secondes entre chaque tage. La temporisation est obtenue par l'appel systme  signaler l'arrive l'tage de l'appel ;  demander l'tage dsir et le lire ;  se dplacer vers l'tage slectionn. Pour sortir de la boucle, entrer un numro d'tage particulier (par exemple 100). Le programme sera structur de la manire suivante :  une fonction  une fonction  une fonction  le numro de l'tage atteint ;

sleep() ;

deplacement(), qui accepte en argument le numro de l'tage dsir et retourne

appel(), qui ralise la lecture de l'tage de la demande ; saisie(), qui ralise la lecture de l'tage atteindre ; une boucle dans la fonction main() qui controle la validit des saisies et termine le programme

dans le cas o l'tage dsir est gal 11.

9.9.2 Exercice 2 : racines d'une quation du deuxime degr


Calcul des racines d'une quation du deuxime degr. Une quation du deuxime degr se prsente sous la forme :

a x2 + b x + c.

Le programme contient 4 fonctions :  calcul du discriminant ;  calcul de la racine double ;  calcul des racines rlles ;  calcul des racines complexes. le programme principal saisit les coecients le bon sous-programme.

a, b

et

c,

il calcule le discriminant et aiguille vers

9.9.3 Exercice 3 : utilisation des chiers d'inclusion


Reprendre l'exercice en mettant les signatures (prototypes) des fonctions dans un chier d'inclusion. Le chier contenant les fonctions reste inchang par rapport au corrig 9.6.

c Christian Bac 1985-2003

122

9.9. EXERCICES SUR LES FONCTIONS ET LA VISIBILIT DES VARIABLES

Programme 9.4 Suggestion de corrig chapitre 9 exercice 1 fonctions


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39

#include <stdio.h> /* PROGRAMME DE SIMULATION DE LA MARCHE D UN ASCENSEUR */ int appel (){ int etg; printf ("Appel ascenseur\n"); printf ("A quel etage etes-vous? de -3 a 10 fin : 11\n"); scanf ("%d", &etg); return etg; } int selection (){ int selec; printf ("Selection etage ? de -3 a 10\n"); scanf ("%d", &selec); return (selec); } int deplacement (int a, int asc){ /* si etage demande > etage d appel */ if(a > asc){ do{ printf ("Etage : %d\n", asc); sleep (2); } while(++asc < a); printf("Arrivee etage %d\n", asc); } /* si etage demande < etage d appel */ else{ do{ printf ("Etage : %d\n", asc); sleep (1); }while(--asc > a); printf("Arrivee etage %d\n", asc); } return asc; }

c Christian Bac 1985-2003

CHAPITRE 9.

COMPILATIONS SPARES

123

Programme 9.5

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

#include <stdio.h>

Suggestion de corrig chapitre 9 exercice 1 main()

extern int appel (); extern int selection (); int deplacement (int, int); int main (int argc, char *argv[], char **envp) { int etg = 0, selec; /* boucle generale */ do{ /* boucle appel */ do selec = appel (); while(selec > 11 || selec < -3); if(selec != 11){ /* deplacement vers l etage d appel */ etg = deplacement (selec, etg); /* boucle de selection */ do selec = selection (); while(selec > 10 || selec < -3); /* deplacement vers l etage destination */ etg = deplacement (selec, etg); } } while(selec != 11); /* test fin */ printf("Arret ascenseur\n"); return 0; }

Donnes en entre
2 4 11

Donnes crites sur le fichier standard de sortie


Appel ascenseur A quel etage etes-vous? de -3 a 10 fin : 11 Etage : 0 Etage : 1 Arrivee etage 2 Selection etage ? de -3 a 10 Etage : 2 Etage : 3 Arrivee etage 4 Appel ascenseur A quel etage etes-vous? de -3 a 10 fin : 11 Arret ascenseur

c Christian Bac 1985-2003

124

9.9. EXERCICES SUR LES FONCTIONS ET LA VISIBILIT DES VARIABLES

Programme 9.6 Suggestion de corrig chapitre 9 exercice 2 fonctions


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #include <stdio.h> /* fonction de calcul du discriminant */ float dis (float a, float b, float c) { return (b * b - 4 * a * c); } /* fonction calculant les racines reelles */ void rac2 (float r, float r1) { printf ("2 racines reelles : %f et %f\n", r + r1, r - r1); } /* fonction calculant les racines complexes */ void complex (float r, float r1) { printf ("2 racines complexes : %f + %f i et %f - %f i\n", r, r1, r, r1); } /* fonction calculant la racine double */ void racd (float r) { printf (" racine double : %f\n", r); }

c Christian Bac 1985-2003

CHAPITRE 9.

COMPILATIONS SPARES

125

Programme 9.7

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

#include <stdio.h> #include <math.h> extern extern extern extern

Suggestion de corrig chapitre 9 exercice 2 main()

float dis (float, float, float); void rac2 (float, float); void complex (float, float); void racd (float);

int main (int argc, char *argv[], char **envp){ float a, b, c, r, r1; double rdis; float res; printf ("calcul des racines de ax2 + bx + c\n\n"); printf ("saisie des valeurs de a b et c"); scanf ("%f", &a); scanf ("%f", &b); scanf ("%f", &c); if (a == 0){ printf (" Equation du premier degre \n"); printf (" La solution est x = %f \n", -c / b); return 0; } r = -b / (2 * a); res = dis (a, b, c); switch (res < 0 ? -1 : (res > 0 ? 1 : 0)){ case 1: rdis = sqrt (res); r1 = rdis / (2 * a); rac2 (r, r1); break; case -1: rdis = sqrt (-res); r1 = rdis / (2 * a); complex (r, r1); break; case 0: racd (r); break; } return 0;

Donnes en entre
2 -4 2

Donnes crites sur le fichier standard de sortie


calcul des racines de ax2 + bx + c saisie des valeurs de a b et c racine double : 1.000000

c Christian Bac 1985-2003

126

9.9. EXERCICES SUR LES FONCTIONS ET LA VISIBILIT DES VARIABLES

Programme 9.8 Suggestion de corrig chapitre 9 exercice 3 chier d'inclusion


1 2 3 4 extern extern extern extern float dis(float, float, float); void rac2(float, float); void complex(float, float); void racd(float);

c Christian Bac 1985-2003

CHAPITRE 9.

COMPILATIONS SPARES

127

Programme 9.9

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36

#include <stdio.h> #include <math.h> #include "c09c03a.h"

Suggestion de corrig chapitre 9 exercice 3 main()

int main (int argc, char *argv[], char **envp){ float a, b, c, r, r1; double rdis; float res; printf ("calcul des racines de ax2 + bx + c\n\n"); printf ("saisie des valeurs de a b et c \n"); scanf ("%f %f %f", &a, &b, &c); if(a == 0){ printf (" Equation du premier degre \n"); printf (" La solution est x = %f \n", -c / b); return 0; } r = -b / (2 * a); res = dis (a, b, c); switch (res < 0 ? -1 : (res > 0 ? 1 : 0)){ case 1: rdis = sqrt (res); r1 = rdis / (2 * a); rac2 (r, r1); break; case -1: rdis = sqrt (-res); r1 = rdis / (2 * a); complex (r, r1); break; case 0: racd (r); break; } return 0; }

Donnes en entre
2 -4 2

Donnes crites sur le fichier standard de sortie


calcul des racines de ax2 + bx + c saisie des valeurs de a b et c racine double : 1.000000

c Christian Bac 1985-2003

128

9.9. EXERCICES SUR LES FONCTIONS ET LA VISIBILIT DES VARIABLES

c Christian Bac 1985-2003

Chapitre 10

Pointeurs et tableaux
Ce chapitre est consacr aux tableaux et leur manipulation travers l'utilisation de pointeurs. Cette utilisation des pointeurs pour accder aux contenus des tableaux est une des dicults du langage pour les dbutants, elle s'avre cependant l'une des techniques les plus utilises par les programmeurs expriments.

10.1 Tableaux une dimension


La dclaration d'un tableau une dimension rserve un espace de mmoire contigu dans lequel les lments du tableau peuvent tre rangs. Comme le montre la gure 10.1, le nom du tableau seul est une constante dont la valeur est l'adresse du dbut du tableau. Les lments sont accessibles par : le nom du tableau, un crochet ouvrant, l'indice de l'lment et un crochet fermant. L'initialisation d'un tableau se fait en mettant une accolade ouvrante, la liste des valeurs servant initialiser le tableau, et un accolade fermante. La gure 10.2 montre l'espace mmoire correspondant la dnition d'un tableau de dix entiers avec une initialisation selon la ligne :

int tab[10] = {9,8,7,6,5,4,3,2,1,0};

Comme le montrent les exemples du programme 10.1, il est possible de ne pas spcier la taille du tableau ou (exclusif ) de ne pas initialiser tous les lments du tableau. Dans ce programme,

tb1

est dni comme un tableau de 6 entiers initialiss, et

tb2

est dni comme un tableau de

Fig.

10.1  Tableau de dix entiers

c Christian Bac 1985-2003

130

10.2.

ARITHMTIQUE D'ADRESSE ET TABLEAUX

Fig.

10.2  Tableau de dix entiers initialis

10 entiers dont les 6 premiers sont initialiss. Depuis la normalisation du langage, l'initialisation des premiers lments d'un tableau provoque l'initialisation de l'ensemble des lments du tableau y compris pour les tableaux locaux. Les lments pour lesquels des valeurs ne sont pas prcises sont initialiss avec la valeur 0 (ensemble des octets zro quelle que soit la taille des lments).

Programme 10.1 Dnition de tableaux et initialisations


int tb1[] = {12,13,4,15,16,32000}; int tb2[10] = {112,413,49,5,16,3200};

Les noms de tableaux tant des constantes, il n'est pas possible de les aecter

1.

10.2 Arithmtique d'adresse et tableaux


Comme nous venons de le dire le nom d'un tableau, correspond l'adresse du premier lment du tableau, de plus les lments d'un tableau sont du mme type. Ces lments ont donc tous la mme taille, et ils ont tous une adresse qui correspond au mme type d'objet (par exemple une adresse d'entier pour chaque lment du tableau exprimes partir du dbut du tableau. Ceci nous amne considrer les oprations possibles partir d'une adresse : calcule une nouvelle adresse de la manire suivante :  l'opration suppose que l'adresse de dpart et l'adresse rsultante sont les adresses deux variables contenues dans le mme tableau.  l'opration suppose aussi que le tableau est d'une taille susamment grande, c'est--dire qu'elle suppose que le programmeur doit tre conscient des risques de dpassement des bornes du tableau. Dans le cas du tableau adresses doivent tre comprises entre de borne, l'adresse immdiatement possible d'crire de  il est possible d'additionner ou de soustraire un entier (n) une adresse. Cette opration

tb1

du programme 10.1). La gure 10.3 reprend

l'exemple de la gure 10.2 en le compltant par les adresses de chaque lment. Ces adresses sont

tab pris en exemple dans la gure 10.3, les &tab[0] et &tab[9]. Pour une question de test

&tab[10]

suprieure la n du tableau est calculable. Il est

mais rien ne garantit que l'expression ne provoque pas une accde. Le compilateur garanti qu'il calcule

erreur si le rang dpasse la taille plus un. La zone mmoire correspondante au rang du tableau plus un ne doit cependant pas tre

1 tb1=
1= .

est une hrsie qui mrite l'exclusion de la communaut des utilisateurs du langage C au mme titre que

c Christian Bac 1985-2003

CHAPITRE 10.

POINTEURS ET TABLEAUX

131

Fig.

10.3  Adresses dans un tableau de dix entiers

Fig.

10.4  Tableau deux dimensions

correctement l'adresse mais il ne garantit pas que le fait d'essayer d'accder la zone mmoire correspondante soit possible.  selon ces conditions, l'addition d'un entier une adresse retourne une adresse qui est celle ime du n objet contenu dans le tableau partir de l'adresse initiale. Dans ces conditions, tab + n est l'adresse du nime entier partir du dbut du tableau. Dans notre exemple variable partir de l'adresse (*) ne peut cependant s'appliquer que pour et 9. Ainsi, Ainsi, de tableau de dix lments,

doit tre compris entre 0 et 10.

L'oprateur d'accs la

*(tab +n)

n'est valide que pour

valant entre 0

compris entre 0 et 9.

 l'addition ou la soustraction d'un entier est possible pour toute adresse dans un tableau.

&tab[3] + 2

donne la mme adresse que

la mme adresse que

&tab[1].

&tab[5].

De mme,

&tab[3] - 2

donne

 il est aussi possible de raliser une soustraction entre les tenant un mme tableau.

adresses de deux variables appar-

Cette opration retourne une valeur du type

correspond au nombre d'objets entre les deux adresses. Ainsi, ner la valeur 2 exprime dans le type la valeur -2 exprime dans le type

ptrdiff_t. ptrdiff_t.

De mme,

ptrdiff_t qui &tab[5] - &tab[3] doit don&tab[3] - &tab[5] retourne

10.3 Tableaux multidimensionnels


Les tableaux deux dimensions sont des tableaux de tableaux. Les indices de droite sont les plus internes. Les tableaux n dimensions sont des tableaux de tableaux n-1 dimensions. La gure 10.4 donne les adresses des sous-tableaux et les noms des dirents lments constitus par la dnition du tableau deux dimensions suivant :

int tab[8][5];.

c Christian Bac 1985-2003

132

10.4.

POINTEURS ET TABLEAUX

Instruction

Interprtation px reoit l'adresse du premier lment du tableau. y reoit la valeur de la variable pointe par px px est incrment de la taille de l'objet point (4 octets). Il contient &x[1]. px reoit l'adresse du ime objet partir de l'objet courant.

px = &x[0] ; y = *px ; px++ ; px = px + i ;

Tab.

10.1  Addition d'un entier un pointeur

10.4 Pointeurs et tableaux


Le

pointeur

est une variable destine contenir une adresse mmoire. Il est reconnu syn-

taxiquement par l'

* lors de sa dclaration. Comme les adresses, le pointeur est associ un type

d'objet. Ce type est celui des objets qui sont manipuls grce au pointeur. L'objet peut tre une variable ou une fonction. Contrairement ce que beaucoup d'apprentis esprent, la dclaration d'un pointeur n'implique pas la dclaration implicite d'une variable associe et l'aectation de l'adresse de la variable au pointeur. Il faut donc dclarer une variable du type correspondant et initialiser le pointeur avec l'adresse de cette variable. Par convention, l'adresse 0 est invalide et si le programme cherche l'accder, il obtient une erreur d'excution du type bus-error sur UNIX. Ce comportement implique que l'utilisation de pointeurs globaux sans initialisation mne ce rsultat, car les pointeurs (comme les autres variables) dclars en variables globales sont initialiss 0. Les pointeurs dclars en variable locale (comme toutes les variables locales) ont des valeurs initiales dpendantes du contenu de la pile cet instant, qui dpend de l'excution prcdent du programme mais correspond en gnral n'importe quoi. Le comportement du programme qui utilise un pointeur local sans l'avoir aect convenablement peut donner des comportements tels que violation de l'espace mmoire, mais parfois le pointeur reoit une adresse valide et le programme se droule sans erreurs agrante mais en donnant des rsultats faux (ce que d'aucuns appellent un eet de bord indsirable, ce que d'autres appellent un bug dicile reproduire). Voici deux exemples de dnition de pointeurs :

int *ptint; pointeur sur un entier char *ptchar; pointeur sur un caractre.

Le compilateur C vrie le type des adresses qui sont aectes un pointeur. Le type du pointeur conditionne les oprations arithmtiques sur ce pointeur. Les oprations possibles sur un pointeur sont les suivantes :  aectation d'une adresse au pointeur ;  utilisation du pointeur pour accder l'objet dont il contient l'adresse ;  addition d'un entier (n) un pointeur ; la nouvelle adresse est celle du l'adresse initiale ;  soustraction de deux pointeurs du mme type. Le calcul est ralis dans les mmes conditions que la dirence entre Le rsultat de type rsultat est indni. Le tableau 10.1 est un exemple de manipulations en relation avec les pointeurs et les tableaux en utilisant les variables : deux adresses de variables contenues dans un mme tableau. La n'est valide que si les adresses contenues dans les deux soustraction calcule le nombre de variables entre les adresses contenues dans les pointeurs.

ne

objet partir de

ptrdiff_t

pointeurs sont bien des

adresses de variables appartenant un mme tableau, sinon le

long x[10], *px , y;

px = (long *) ( (int) px + i * sizeof (long));

L'addition dcrite dans la dernire ligne du tableau 10.1 se traduit par les conversions suivantes :

c Christian Bac 1985-2003

CHAPITRE 10.

POINTEURS ET TABLEAUX

133

Instruction

Interprtation pt1 reoit l'adresse du premier lment du tableau. pt2 reoit l'adresse du dixime lment du tableau. i reoit la dirence des deux pointeurs pt1 et pt2. soit le nombre d'objets entre pt2 et pt1. i contiendra 10 la n de cette instruction.

pt1 = &tab[0] ; pt2 = &tab[10] ; i = pt2 - pt1 ;

Tab.

10.2  Soustraction de deux pointeurs

int tab[20], *pt1, *pt2; ptrdiff_t i;

Le tableau 10.2 est un exemple de soustraction partir des dnitions de variables suivantes :

Par convention, le nom d'une variable utilis dans une partie droite d'expression donne le contenu de cette variable dans le cas d'une variable simple. Mais un nom de tableau donne l'adresse du tableau qui est l'adresse du premier lment du tableau. Nous faisons les constatations suivantes :  un tableau est une  un pointeur est une les variables :  

constante d'adressage ; variable d'adressage.

Ceci nous amne regarder l'utilisation de pointeurs pour manipuler des tableaux, en prenant

long i, tab[10], *pti ; tab est l'adresse du tableau (adresse du premier lment du tableau &tab[0] ; pti = tab ; initialise le pointeur pti avec l'adresse du dbut de tableau. Le & ne sert rien dans le cas d'un tableau. pti = &tab est inutile et d'ailleurs non reconnu ou ignor par

certains compilateurs ;  

&tab[1] est l'adresse du 2e lment du tableau. pti = &tab[1] est quivalent :  pti = tab ; o pti pointe sur le 1er lment du tableau.  pti += 1 ; fait avancer, le pointeur d'une case ce qui fait
2me lment du tableau. De mme,

qu'il contient l'adresse du

+ i).

Nous pouvons dduire de cette arithmtique de pointeur que :

*(pti+i)

est quivalent pti[i].

tab[i] est quivalent *(tab

La gure 10.5 est un exemple dans lequel sont dcrites les direntes faons d'accder au lments d'u tableau

tab et du pointeur pt aprs la dnition suivante : int tab[8], *pt = tab;

10.5 Tableau de pointeurs


La dnition d'un tableau de pointeurs se fait par :

type *nom[taille] ;

argv et envp de la fonction main() que nous avons eu l'occasion d'aborder dans la section 8.7 et que nous
contiennent les adresses des lments du tableau de variables. C'est le cas des arguments avons reprsents dans la gure 8.5. La gure 10.6 est un exemple d'utilisation de tableau de pointeurs partir des dnitions de variables suivantes :

Le premier cas d'utilisation d'un tel tableau est celui o les lments du tableau de pointeurs

int tab[8], *pt[8] = {tab,tab+1,tab+2,tab+3,tab+4,tab+5,tab+6,tab+7};

c Christian Bac 1985-2003

134

10.5. TABLEAU DE POINTEURS

Fig.

10.5  Pointeur et tableau

Fig.

10.6  Tableau de pointeurs sur des variables dans un tableau

c Christian Bac 1985-2003

CHAPITRE 10.

POINTEURS ET TABLEAUX

135

Fig.

10.7  Accs un tableau deux dimensions avec un pointeur

10.6 Pointeurs vers un tableau


Un pointeur peut contenir l'adresse d'une variable assez complexe comme un tableau dans sa globalit ou une structure dont nous parlerons dans le chapitre 11. Ce type de pointeur permet par exemple de manipuler les sous-tableaux d'un tableau deux dimensions. Nous verrons de manire plus dtaille dans la section 14.2 les rgles de lecture et d'criture d'une dclaration complexe, en suivant ces rgles, un pointeur sur un tableau pris dans sa globalit se dclare par :

(*nom)[taille] ;

type

La gure 10.7 dcrit les direntes faons d'accder aux variables d'un tableau de six fois cinq entiers (certains diraient un tableau de 6 lignes et 5 colonnes) partir d'un pointeur qui peut contenir une adresse de sous-tableau (de cinq entiers).

int tab[6][5]; tableau de 6 fois 5 entiers. int (*pt)[5]= tab;


Le programme 10.2 montre les direntes manires d'accder aux lments du tableau dni ci-dessus par le pointeur associ.

10.7 Exercices sur les tableaux et les pointeurs


10.7.1 Exercice 1 : tri de tableaux d'entiers
L'exercice consiste lire des entiers dans un tableau, sparer les nombres pairs et les impairs en les mettant dans deux tableaux, puis trier chacun des deux tableaux. Les tableaux ont une taille arbitraire de 100. La lecture des entiers se termine lors de la saisie de 0, cet entier est mis dans le tableau et il est consider comme une sentinelle de n de tableau. c Christian Bac 1985-2003

136

10.7. EXERCICES SUR LES TABLEAUX ET LES POINTEURS

La sparation entre nombres pairs et impairs est faite dans une fonction qui reoit en arguments les adresses des trois tableaux (adresse de l'lment de rang 0 du tableau), cette fonction termine les tableaux pairs et impairs par des zros. Le tri de chaque tableau est realis par une fonction permet de vrier la validit de l'ensemble. Le programme doit tre compos d'un chier source qui contient les fonctions etd'un autre qui contient la fonction

tri(int *)

qui utilise un algorithme de

tri simple, un exemple d'algorithme est donn la n de ce texte. La rcriture des tableaux tris

main()

et d'un chier d'inclusion qui permet de faire la liaison pour le

compilateur entre les deux chiers. Le fait de mettre des zros en n de tableau peut vous suggrer de manipuler ces tableaux avec des pointeurs. Le programme 10.3 est un exemple d'algorithme de tri d'un tableau termin par un zro.

c Christian Bac 1985-2003

CHAPITRE 10.

POINTEURS ET TABLEAUX

137

Programme 10.2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

#include <stdio.h>

Accs un tableau deux dimensions avec un pointeur

int main (int argc, char *argv[]) { int tab[6][5]; int (*pt)[5]= tab; int i,j; for(i=0;i<6;i++) for(j=0;j<5;j++) tab[i][j]= i*10+j; for(i=2;i<6;i++) for(j=3;j<5;j++){ printf("tab[%d][%d] = %d\t",i,j,tab[i][j]); printf("%d\t",*(tab[i]+j)); printf("%d\t",*(*(tab+i)+j)); printf("%d\t",*(*(pt+i)+j)); printf("%d\t",*(pt[i]+j)); printf("%d\n",pt[i][j]); } return 0;

Donnes crites sur le fichier standard de sortie


tab[2][3] tab[2][4] tab[3][3] tab[3][4] tab[4][3] tab[4][4] tab[5][3] tab[5][4] = = = = = = = = 23 24 33 34 43 44 53 54 23 24 33 34 43 44 53 54 23 24 33 34 43 44 53 54 23 24 33 34 43 44 53 54 23 24 33 34 43 44 53 54 23 24 33 34 43 44 53 54

c Christian Bac 1985-2003

138

10.7. EXERCICES SUR LES TABLEAUX ET LES POINTEURS

Programme 10.3 Algorithme d'un tri simple


i = 0; Tant que tab[i] faire j = i + 1; Tant que tab[j] faire si tab[j] est inferieur a tab[i] alors faire echanger tab[j] et tab[i] fait finsi j++; fait i++; fait

Programme 10.4 Suggestion de corrig chapitre 10 exercice 1 chier d'inclusion


1 2 3 4 5 6

extern int saisie(int []); /* fonction de saisie de tableau * retourne le nombre d'entiers saisis */ extern void tri(int []); /* fonction de tri de tableau pointe */ extern void imptab(int [],int); /* fonction d'impression du tableau */ extern int separ(int [],int [],int []); /*separation pairs/impairs */

c Christian Bac 1985-2003

CHAPITRE 10.

POINTEURS ET TABLEAUX

139

Programme 10.5 Suggestion de corrig chapitre 10 exercice 1 fonctions


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 #include <stdio.h> int /* fonction de saisie du tableau a manipuler */ saisie (int ti[]){ int *ptab = ti; printf (" Entrer des entiers \n"); printf (" Terminer la liste avec 0\n\n"); do scanf ("%d", ptab); while (*ptab++ != 0); return ptab - ti; } int /* separation des pairs et des impairs en deux tableaux */ separ (int t[], int tp[], int ti[]){ register int *pttab = t, *ptimp = ti, *ptpair = tp; while (*pttab) if (*pttab & 0x01) *ptimp++ = *pttab++; else *ptpair++ = *pttab++; *ptimp = *ptpair = 0; /* chien de garde de fin de tableau */ return pttab - t; /* nombre d entiers traites */ } void /* fonction d'impression du tableau */ imptab (int tri[], int type){ register int *ptri = tri, i; if (type == 0) printf ("\n\tImpression du tableau initial \n"); else if (type == 1) printf ("\n\tImpression du tableau impair \n"); else printf ("\n\tImpression du tableau pair \n"); i = 0; while (*ptri){ printf (" %6d ", *ptri++); if (!*ptri) break; if (i++ && !(i % 8)) printf ("\n"); } }

c Christian Bac 1985-2003

140

10.7. EXERCICES SUR LES TABLEAUX ET LES POINTEURS

Programme 10.6

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

main #include <stdio.h> #include "c10c01a.h" /* programme principal realisant les operations suivantes : * - saisie du tableau * - separation des nombres pairs et impairs * - appel de la fonction de tri * - appel de la fonction impression. */ int tab[100], imp[100], pair[100]; int main (int argc, char *argv[], char **envp){ register int count; /* definition de 3 pointeurs */ /* saisie du tableau a manipuler */ count = saisie (tab); printf (" Vous avez saisi %d nombres dans le tableau\n", count); /* separation des pairs et des impairs en deux tableaux */ count = separ (tab, pair, imp); printf (" Nous avons spar %d nombres dans le tableau\n", count); tri (tab); /* tri et impression */ imptab (tab, 0); tri (imp); /* tri et impression */ imptab (imp, 1); tri (pair); /* tri et impression */ imptab (pair, 2); return 0; }

Suggestion de corrig chapitre 10 exercice 1

Donnes en entre
1 -2 4 7 -6 29 123 -345 -12 3 0

Donnes crites sur le fichier standard de sortie


Entrer des entiers Terminer la liste avec 0 Vous avez saisi 11 nombres dans le tableau Nous avons spar 10 nombres dans le tableau Impression -345 29 Impression -345 Impression -12 du tableau initial -12 -6 -2 123 du tableau impair 1 3 7 du tableau pair -6 -2 4 1 29 3 123 4 7

c Christian Bac 1985-2003

CHAPITRE 10.

POINTEURS ET TABLEAUX

141

Programme 10.7 Suggestion de corrig chapitre 10 exercice 1 fonction de tri

1 void 2 tri (int ti[]){ /* fonction de tri de tableau pointe par ptint */ 3 register int tamp, *ptrj, *ptint = ti; 4 while(*ptint){ 5 ptrj = ptint + 1; 6 while(*ptrj){ 7 if(*ptrj < *ptint){ 8 tamp = *ptint; 9 *ptint = *ptrj; 10 *ptrj = tamp; 11 } 12 ptrj++; 13 } 14 ptint++; 15 } 16 }

c Christian Bac 1985-2003

142

10.7. EXERCICES SUR LES TABLEAUX ET LES POINTEURS

c Christian Bac 1985-2003

Chapitre 11

Structures
Une structure est une variable compose de plusieurs champs qui sert reprsenter un objet rel ou un concept. Par exemple une voiture peut tre reprsente par les renseignements suivants : la marque, la couleur, l'anne, . . .

11.1 Dnition
Le langage C permet de dnir des modles de structures comme les autres langages volus. Cela se fait selon la dnition donne par l'encart suivant.

struct

nom_de_structure type1 nom_champ1 ; type2 nom_champ2 ; type3 nom_champ3 ; type4 nom_champ4 ; typeN nom_champ_N ; variables ;
...

Une dnition de ce type sert dnir un modle de structure associ un nom de modle, qui est optionnel, et dnir des variables construites partir de ce modle (cette dnition est optionnelle aussi). Comme le montre l'exemple 11.1 dans les lignes 2 4, il est possible de ne pas dclarer de

variable la dnition de la structure, dans ce cas, le modle de structure doit tre associ un nom de manire pouvoir utiliser celui-ci pour dnir des variables ultrieurement. La dnition d'une structure ne rserve pas d'espace mmoire. Il faut dnir les correspondant ce modle de structure (ligne 6). Il est aussi possible de ne pas associer un nom de modle la dnition de la structure. Les objets de ce type devront tre dclars immdiatement (lignes 8 11). Ce modle de structure ne peut pas tre rfrenc par la suite, puisqu'il n'a pas de nom. Il est dit anonyme. c Christian Bac 1985-2003

variables

144

11.2.

UTILISATION

Programme 11.1 Dnition de structures


1 2 3 4 5 6 7 8 9 10 11 struct date { int jour, mois, annee ; } ; struct date obdate, *ptdate = &obdate; struct { int jour, mois ; char annee[20] ; } ob1, *pt1;

Objet

Pointeur

obdate.jour = 1 ; obdate.mois = 1 ; obdate.annee = 85 ;

ptdate->jour = 1 ; ptdate->mois = 1 ; ptdate->annee = 85 ;

Tab.

11.1  Accs aux champs d'une structure

11.2 Utilisation
Les structures peuvent tre manipules champ par champ ou dans leur ensemble.

11.2.1 Oprations sur les champs


L'accs aux lments d'une structure, que nous appelons aussi champs, se fait en utilisant le nom de la variable suivi d'un point et du nom du champ dsir : Pour accder aux champs d'une structure partir d'un

pointeur

nom_de_variable.nom_du_champ.

associ avec une struc-

ture, il faut remplacer le point par un moins suivi d'un suprieur (qui symbolise une che) :

nom_de_variable->nom_du_champ.
le montre le tableau 11.1.

Une fois ces dnitions ralises, nous pouvons utiliser les variables

obdate

et

ptdate

comme

En prenant les dnitions de donnes dans le programme 11.1 dans les lignes 2 6, le tableau 11.1, donne les direntes possibilits d'aectation pour chaque champ. Nous remarquerons l'quivalence entre :

(*ptdate).jour

et

ptdate->jour

Pour le compilateur, l'accs un champ d'une structure consiste faire un calcul de dplacement par rapport au dbut de la structure puis accder une variable cette adresse.

11.2.2 Oprations sur la variable dans son ensemble


La normalisation du langage C a institutionalis une pratique qui tait dj courante dans de nombreux compilateurs qui consiste considrer une variable construite partir d'un type structur comme une variable simple. Il est possible de construire une fonction qui accepte en argument ou qui retourne une structure.

En prenant les dnitions de variables et de fonctions du programme 11.2, les oprations suivantes sont possibles sur les structures : c Christian Bac 1985-2003

CHAPITRE 11.

STRUCTURES

145

Programme 11.2 Dnition de structures


1 2 3 4 5 6 7 8 9 struct date { int jour, mois, annee ; } ; struct date obdate, obdate2e; extern struct date newdate() ; extern int checkdate(struct date) ; int resul ;

1. l'aectation d'un variable par une autre du mme type comme 2. le 3. le

obdate = obdate2 ; retour d'une structure par une fonction comme obdate = newdate() ; passage en argument d'une structure une fonction. resul = checkdate(obdate2).

11.3 Structures et listes chanes


La syntaxe du langage C autorise les dnitions de structure contenant des pointeurs sur ce type de structure. Ceci permet de faire des listes chanes comme le montre le programme 11.3.

Programme 11.3 Structures et listes chanes


1 2 struct noeud { 3 int val ; 4 struct noeud *suiv ; 5 struct noeud *pred ; 6 } node, tab[100] , *ptnoeud = tab ;

Note sur les pointeurs de structures : nous avons vu dans le chapitre prcdent sur l'aritmthique des adresses que l'incrmentation d'un pointeur le faisait passer sur l'lment suivant lorsque le pointeur contient une adresse qui correspond un tableau d'lments correspondants au type de variable associ au pointeur. Il en est de mme pour un pointeur qui contient une adresse de structure. Un pointeur incrment permet l'accs la structure suivante lorsque les structures sont dans un tableau. Reprenons le programme 11.3 dans lequel nous avons dni un tableau de structures et un pointeur sur la structure noeud.

ptnoeud

Aprs la dnition la variable pointe sur

tab[1].

ptnoeud pointe alors sur tab[0] et si nous crivons : ptnoeud++ ;

11.4 Champs de bits


Les structures donnent accs un dcoupage des octets pour obtenir des variables qui sont dcrites sur un ensemble d'lments binaires dont la taille est infrieure celle de l'octet. Il est en eet possible de dcouper logiquement un ensemble d'octets en des ensembles de bits. La prcision de la longueur de chaque champ est faite par l'ajout de  suivant. c Christian Bac 1985-2003

: longueur

 chaque

lment de la structure. Les structures de champs de bits sont dclares selon le modle de l'encart

146

11.5.

EXERCICES SUR LES STRUCTURES

struct nom_de_structure unsigned nom_champ1 unsigned nom_champ2 unsigned nom_champ3 unsigned nom_champ4
...

: : : :

longueur1 ; longueur2 ; longueur3 ; longueur4 ;

unsigned nom_champ_N

: longueurN ; objets ;

Il est recommand de n'utiliser que des lments de type unsigned. La norme X3J11 n'impose pas que d'autres types soient supports. Un champ sans nom, avec simplement la taille, est un champ de remplissage pour cadrer sur des frontires de mot machine. Le programme 11.4 donne quelques exemples de dnitions de modles de structures correspondant des champs de bits :

Programme 11.4 Structures et champs de bits


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 struct mot { unsigned sign:1; unsigned val:15; };

struct flottant { unsigned exposant:7; unsigned signe:1; unsigned mantisse:24; }; struct mixte { unsigned exposant:7; unsigned signe:1; unsigned mantisse:24; unsigned comp:7; unsigned : 9; };

11.5 Exercices sur les structures


11.5.1 Exercice 1
Dnir une structure date contenant trois champs de type entier pour identier le jours, le mois et l'anne. Initialiser une variable de type structure date. Imprimer cette structure :  l'aide de la variable.  l'aide d'un pointeur. c Christian Bac 1985-2003

CHAPITRE 11.

STRUCTURES

147

Programme 11.5

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

#include <stdio.h> struct date /* declaration du modele de structure date */ { int jour; int mois; int annee; };

Suggestion de corrig chapitre 11 exercice 1

int main (int argc, char *argv[], char **envp) { struct date dat, *ptdate = &dat; /* saisie de la date */ printf (" Entrez une date ( jj mm aaaa ) :"); scanf ("%d %d %d", &dat.jour, &dat.mois, &dat.annee); /* impression de la date */ printf (" La date est : %d\t%d\t%d\n", dat.jour, dat.mois, dat.annee); /* impression de la date avec le pointeur */ printf (" La date est : %d\t%d\t%d\n", ptdate->jour, ptdate->mois, ptdate->annee); return 0; }

Donnes en entre
01 04 2003

Donnes crites sur le fichier standard de sortie


Entrez une date ( jj mm aaaa ) : La date est : 1 4 2003 La date est : 1 4 2003

11.5.2 Exercice 2
Dnir un tableau de structures date. Dnir un pointeur sur ce tableau. Initialiser ce tableau. Imprimer le contenu du tableau.

c Christian Bac 1985-2003

148

11.5.

EXERCICES SUR LES STRUCTURES

Programme 11.6

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

#include <stdio.h> /* declaration du modele de structure date */ struct date{ int jour, mois, annee;}; int main (int argc, char *argv[], char **envp) { struct date dat[5], *ptdate=dat; int i = 0; /* remplissage du tableau */ printf ("Entrez 5 dates au format ( jj mm aaaa )\n"); while (i < 5){ scanf ("%d %d %d", &dat[i].jour, &dat[i].mois, &dat[i].annee); i++; } /* impression du tableau */ for (i = 0; i < 5; i++, ptdate++) { /* sans pointeur */ printf (" Date numero %d : %d\t%d\t%d\n", i + 1, dat[i].jour, dat[i].mois, dat[i].annee); /* avec pointeur */ printf (" Date numero %d : %d\t%d\t%d\n", i + 1, ptdate->jour, ptdate->mois, ptdate->annee); } return 0; }

Suggestion de corrig chapitre 11 exercice 2

Donnes en entre
01 03 09 02 11 04 05 08 09 11 2003 2003 2003 2003 2003

Donnes crites sur le fichier standard de sortie


Entrez 5 dates Date numero 1 Date numero 1 Date numero 2 Date numero 2 Date numero 3 Date numero 3 Date numero 4 Date numero 4 Date numero 5 Date numero 5 au format ( jj mm aaaa ) : 1 4 2003 : 1 4 2003 : 3 5 2003 : 3 5 2003 : 9 8 2003 : 9 8 2003 : 2 9 2003 : 2 9 2003 : 11 11 2003 : 11 11 2003

c Christian Bac 1985-2003

Chapitre 12

Unions
Les

unions

permettent l'utilisation d'un mme espace mmoire par des donnes de types

dirents des moments dirents.

12.1 Dnition
La dnition d'une union respecte une syntaxe proche de celle d'une structure et qui est donne dans l'encart suivant.

union

nom_de_union type1 nom_champ1 ; type2 nom_champ2 ; type3 nom_champ3 ; type4 nom_champ4 ; typeN nom_champ_N ; variables ;
z1
et

...

Le programme 12.1 dnit deux variables avec point dcimal long.

z2

construites sur le modle d'une zone qui

peut contenir soit un entier, soit un entier long, soit un nombre avec point dcimal, soit un nombre

Programme 12.1 Utilisation d'une union


1 union zone { 2 int entier; 3 long entlong; 4 float flottant; 5 double flotlong; 6 } z1,z2;

Lorsque l'on dnit une variable correspondant un type union, le compilateur rserve l'espace mmoire ncessaire pour stocker le plus grand des champs appartenant l'union. Dans notre exemple, le compilateur rserve l'espace mmoire ncessaire pour stocker un des variables

z1

et

z2.

double pour chacune

c Christian Bac 1985-2003

150

12.2.

ACCS AUX CHAMPS

12.2 Accs aux champs


La syntaxe d'accs aux champs d'une union est identique celle pour accder aux champs d'une structure (voir section 11.2.1). Une union ne contient cependant qu'une donne la fois et l'accs un champ de l'union pour obtenir une valeur, doit tre fait dans le type qui a t utilis pour stocker la valeur. Si cette uniformit n'est pas respecte dans l'accs, l'opration devient dpendante de la machine. Les unions ne sont pas destines faire des conversions. Elles ont ts inventes pour utiliser un mme espace mmoire avec des types de donnes dirents dans des tapes direntes d'un mme programme. Elles sont, par exemple, utilises dans les compilateurs. Les dirents champs d'une union sont la mme adresse physique. Ainsi, les galits suivantes sont vraies :

&z1.entier == (int*)&z1.entlong &z1.entier == (int*)&z1.flottant &z1.entier == (int*)&z1.flotlong


Programme 12.2

1 2 3 4 5 6 7 8 9 10 11 12 13

#include <stdio.h> int main (int argc, char *argv[]) { union etiq { short int ent; unsigned short int ent1; } lmot = { -1, }; printf ("Valeur de lmot.ent : %hd\n", lmot.ent); printf ("Valeur de lmot.ent1 : %hd\n", lmot.ent1); return 0; }

Utilisation d'une union

Donnes crites sur le fichier standard de sortie


Valeur de lmot.ent : -1 Valeur de lmot.ent1 : 65535
Dans l'exemple 12.2, la zone mmoire correspondant la variable ou avec signe. Ainsi si la valeur est vue travers

lmot peut tre vue sans signe -1 est aecte lmot.ent. Cette valeur peut tre considre comme lmot.ent1.
Ainsi le programme 12.1 donne le rsultat suivant :

plus grande que zro (puisque gale USHRT_MAX ou 65535U) ou plus petite suivant qu'elle

lmot.ent

ou

Valeur de lmot.ent : -1 Valeur de lmot.ent1 : 65535

12.3 Exercices sur les unions et les champs de bits


12.3.1 Exercice 1
Dnir une union pouvant contenir une variable des types suivants : entier, rel et caractre. Pour chacun des membres de l'union : c Christian Bac 1985-2003

CHAPITRE 12.

UNIONS

151

 lire une valeur correspondante au clavier ;  acher l'adresse du membre ;  puis acher son contenu.

Programme 12.3

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

#include <stdio.h> union test { /* definition du modele de l'union */ char un_char; int un_int; float un_float; } ; int main (int argc, char *argv[], char **envp) { union test un_test; /* saisie du caractere et impression */ printf(" Entrer un caractere : "); scanf("%c",&un_test.un_char); printf(" caractere : %c \t adresse : %x \n", un_test.un_char, &un_test.un_char); /* saisie de l'entier et impression */ printf(" Entrer un entier : "); scanf("%d",&un_test.un_int); printf(" entier : %d \t adresse : %x \n", un_test.un_int, &un_test.un_int); /* saisie du flottant et impression */ printf(" Entrer un flottant : "); scanf("%f",&un_test.un_float); printf(" flottant : %f \t adresse : %x \n", un_test.un_float, &un_test.un_float); return 0; }

Suggestion de corrig chapitre 12 exercice 1

Donnes en entre
c 22 3.14159

Donnes crites sur le fichier standard de sortie


Entrer un caractere : caractere : c adresse : bffff564 Entrer un entier : entier : 22 adresse : bffff564 Entrer un flottant : flottant : 3.141590 adresse : bffff564

12.3.2 Exercice 2
Denir un champ de bits compos de :  2 bits,  7 bits pour un premier caractre,  7 bits pour un deuxime caractre,  16 bits pour un entier. Initialiser ce champ de bits. Imprimer ce champ en hexadcimal. c Christian Bac 1985-2003

152

12.3.

EXERCICES SUR LES UNIONS ET LES CHAMPS DE BITS

Imprimer les direntes composantes de ce champ.

Programme 12.4

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

#include <stdio.h> struct champ_bit { /* definition du champ de bits */ unsigned left : 2; unsigned car1 : 7; unsigned car2 : 7; unsigned nbre : 16; } champ = { 01, 'a', 'Z', 4532 }; /* initialisation */ int main (int argc, char *argv[], char **envp) { /* impression du champ globalement */ printf(" Valeur du champ : %x\n", champ); /* impression de chaque partie du champ */ printf(" Caractere 1 : %c\n", champ.car1); printf(" Caractere 1 : %x\n", champ.car1); printf(" Caractere 2 : %c\n", champ.car2); printf(" Caractere 2 : %x\n", champ.car2); printf(" Nombre : %d\n", champ.nbre); printf(" Nombre : %x\n", champ.nbre); printf(" Bits de gauche : %x\n", champ.left); return 0; }

Suggestion de corrig chapitre 12 exercice 2

Donnes crites sur le fichier standard de sortie


Valeur du champ : 11b4b585 Caractere 1 : a Caractere 1 : 61 Caractere 2 : Z Caractere 2 : 5a Nombre : 4532 Nombre : 11b4 Bits de gauche : 1

c Christian Bac 1985-2003

Chapitre 13

numrations
Les numrations servent orir des possibilits de gestion de constantes numres dans le langage C. Ces numrations sont un apport de la norme ANSI et permettent d'exprimer des valeurs constantes de type entier en associant ces valeurs des noms. Les numrations orent une alternative l'utilisation du pr-processeur dans la description de constantes (voir chap. 15).

13.1 Dnition
La dnition d'une numration respecte la syntaxe donne dans l'encart suivant.

enum

nom_de_numration { numrateur1, numrateur2, numrateur3, numrateur4,


...

numrateurN variables ;

Les dirents numrateurs sont des constantes symboliques. Les valeurs associes aux numrateurs sont, par dfaut, dnies de la manire suivante : la premire constante est associe la valeur

0,

les constantes suivantes suivent une progression de 1.

Il est possible de xer une valeur chaque numrateur en faisant suivre l'numrateur du signe gal et de la valeur entire exprime par une constante ; si l'numrateur suivant n'est pas associ une valeur, la progression de 1 reprend la valeur courante. Nous baserons nos exemples sur le programme 13.1. Les lignes 2 et 3 de cet exemple d'numration dnissent les constantes symboliques : 1. 2. 3.

rouge vert bleu

qui correspond la valeur 0 ;

qui correspond la valeur 1 ; qui correspond la valeur 2.

Elles dnissent la variable

rvb

construite sur ce modle d'numration. Cette partie utilise les

possibilits standard des numrations. c Christian Bac 1985-2003

154

13.2.

UTILISATION

Programme 13.1 Utilisation d'numrations


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #include <stdio.h> enum couleurs { rouge, vert, bleu } rvb; enum autrescouleurs { violet=4, orange, jaune=8 } arcenciel; enum typefic { normal = 0100000, repertoire = 0040000, special_bloc = 0060000, special_car = 0020000, sock_unix = 0140000, tube_nomme = 0010000, lien_symb = 0120000 }tfic; int main (int argc, char *argv[]) { rvb = 12 ; arcenciel = violet + jaune; if(rvb == arcenciel) tfic = repertoire; else tfic = normal; rvb = sock_unix; return 0; }

Les lignes 5 7 xent les valeurs de certains numrateurs eet dnissent les constantes symboliques suivantes : 1. 2. 3.

violet orange jaune

qui est associe la valeur 4 ; qui correspond la valeur 5 (violet

+ 1) ;

qui est associe la valeur 8.

Elles dnissent la variable

arcenciel

construite sur le modle d'numration

autrescouleurs.

Les lignes 8 16 montrent une utilisation des numrations pour direncier les types de chiers dans les inodes d'un systme de chiers de type UNIX.

13.2 Utilisation
Les numrateurs peuvent tre utiliss dans des expressions du langage la mme place que des constantes du type entier. Ainsi, ils peuvent se situer dans des calculs, pour aecter des variables et pour raliser des tests. c Christian Bac 1985-2003

CHAPITRE 13.

NUMRATIONS

155

13.3 Limites des numrations


Les numrations sont des types synonymes (voir chap. 14) du type entier. Ceci prsente l'avantage de pouvoir raliser des expressions combinant des variables de type numr avec des entiers. Elles permettent d'utiliser des constantes symboliques. Les variables dnies partir de type numr sont cependant traites comme des entiers. Le compilateur n'impose pas qu'une variable de type numr soit aecte avec une des valeurs correspondant aux constantes symboliques associes avec ce type. Ainsi nous pouvons crire les lignes 20, 22 et 26 du programme 13.1 sans que le compilateur proteste. Dans ces lignes nous mlangeons les constantes symboliques appartenant des types d'numration dirents sans avoir de message d'avertissement du compilateur.

c Christian Bac 1985-2003

156

13.3.

LIMITES DES NUMRATIONS

c Christian Bac 1985-2003

Chapitre 14

Types synonymes et complexes


Ce chapitre aborde la dnition de types complexes.

14.1 Types synonymes


Il est possible grce au dclarateur nonyme. L'introduction du mot rserv

typedef de dnir un type nouveau qui est un type sytypedef comme premier mot d'une ligne de dnitions typedef.

provoque le fait que les noms qui seraient des noms de variables sur la mme ligne sans ce mot rserv deviennent des noms de types synonymes. Chaque nom de type synonyme correspond au type qu'aurait eu la variable sur la mme ligne sans Ainsi la dnition suivante :

typedef int entier ;


dnit un type synonyme appel

entier ayant les mmes caractristiques que le type prdni int.

Une fois cette dnition ralise, nous pouvons utiliser ce nouveau type pour dnir des variables et nous pouvons mlanger les variables de ce type avec des variables entires pour raliser des expressions.

entier e1=23, e2=5, te[50]={1,2,3,4,5,6,7}; int i; i = e1 + e2; te[20] = i - 60;


Dans le cas de la dclaration de tableaux, la taille du nouveau type se trouve aprs le nouveau nom de type.

typedef int tab[10]; tab tt ;


Dans cet exemple, variable

tt

tab

devient un type synonyme correspondant au type tableau de 10

int.

La

est un tableau de 10 entiers. est trs semblable une directive du pr-processeur (chap. 15) mais il s'adresse au

typedef
compilateur.

Attention : typedef ne rserve pas d'espace mmoire. Les noms sont des types ; ils sont donc
inaccessibles comme variables. c Christian Bac 1985-2003

158

14.2. TYPES COMPLEXES

L'utilisation de

typedef

permet de faciliter les dnitions de prototypes pour permettre aux

programmeurs d'crire du code plus lisible. Il est aussi possible de dnir un type quivalent une structure :

typedef struct { int jour ; int mois ; int annee ; } date ;


et d'utiliser directement ce type. Ceci vite les rptitions fastidieuses du mot rserv

struct.

date obdate, *ptdate ; obdate est un objet correspondant au type date qui est synonyme d'une structure anonyme jour, mois et annee. La variable ptdate est un pointeur qui peut contenir l'adresse d'une variable du type date mais qui dans l'exemple n'est pas initialis.
Ainsi contenant trois variables entires appeles

14.2 Types complexes


Nous allons nous intresser aux types complexes sous l'angle du lecteur d'un programme crit par un autre rdacteur. Ainsi notre premier objectif est de pouvoir comprendre une ligne comprenant des dclarations ou des dnitions de variables qui semblent premire vue complexes. Pour raliser cette lecture correctement nous appliquerons la rgle suivante :  il faut partir du nom de l'objet ;  et ensuite il faut appliquer les rgles de prcdence des le tableau 5.6. Les parties du tableau de prcdence qui nous intressent dans cette entreprise sont celles qui portent sur les parenthses correspondant aux regroupement ou aux fonctions, aux crochets correspondant aux tableaux, et aux toiles correspondant aux pointeurs. Parmi ces quatre oprateurs les rgles de prcdences sont les suivantes :   oprateurs telles que donnes dans

()

reprsentant le regroupement est de priorit la plus leve et une associativit de gauche correspondant l'identication d'une fonction et

droite ;

() *

[]

correspondant la dnition d'un

tableau sont de priorit gale et immdiatement infrieure au regroupement avec une associativit de gauche droite ;  est de priorit la plus basse parmi nos quatre oprateurs avec une associativit de droite gauche. Le tableau 14.1 donne un ensemble de dnitions de variables et dcrit le type de chaque variable.

14.3 Fonctions et tableaux


Comme le montre les exemples prcdents, il est possible de dnir des tableaux de pointeurs sur une fonction.

int (*t1[10])(); int *(*t2[10])();


c Christian Bac 1985-2003

CHAPITRE 14.

TYPES SYNONYMES ET COMPLEXES

159

Dclaration

Objet tableau de 10 pointeurs d'entier tableau de 10 pointeurs sur des pointeurs d'entier pointeur sur un tableau de 10 entiers pointeur sur un tableau de 10 pointeurs sur un entier fonction qui retourne un pointeur sur un entier pointeur sur une fonction qui retourne un entier Modle d'union de deux structures de type t1 et t2

int *tab[10] ; int **ta[10] ; int (*tb)[10] ; int *(*tb)[10] ; int *fp() ; int (*fp)() ; union u { struct t1 u1 ; struct t2 u2 ; } int tt()[10] ; int tt[10]() ; int (*t1[10])() ; int *(*t2[10])() ; int t3[] ; int *t4[] ; int t5[][] ; int **t7 ; float (*pf[5])()= {sin,cos}

dnition illgale fonction qui retourne un tableau. dnition illgale tableau de fonctions Tableau de 10 adresses de fonctions qui retournent un entier Tableau de 10 adresses de fonctions qui retournent un pointeur d'entier tableau de taille inconnue la dnition de l'objet est obligatoirement externe tableau de pointeurs externe dclaration illgale il faut xer la taille de la 2 dimension Pointeur sur un pointeur d'entier (Souvent utilis pour dcrire un tableau de pointeurs d'entier) Tableau de pointeurs sur des fonctions qui retournent des initialises par les adresses de

float
et

Les deux premires entres du tableau sont

cos

sin

Tab.

14.1  Exemples d'objets complexes

c Christian Bac 1985-2003

160

14.4. EXERCICES SUR LES DCLARATIONS COMPLEXES

Le premier exemple dnit un tableau de 10 pointeurs qui peuvent recevoir des adresses de fonctions qui retournent un entier. Le second exemple dnit un tableau de 10 pointeurs de fonctions qui peuvent recevoir des adresses de fonctions qui retournent un pointeur sur un entier. En langage C, le nom d'une fonction est considr comme une adresse et l'appel d'une fonction consiste d-rfrencer son adresse pour provoquer un saut du pointeur de programme courant cette adresse.

14.4 Exercices sur les dclarations complexes


14.4.1 Exercice 1
Dnir les types suivants :  structure date telle que dnie dans le programme 11.5,  pointeur sur une structure date,  tableau de dix objets de structure date.

Programme 14.1

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

struct date /* definition du modele de structure date */ { int jour, mois, annee; }; /* definition des types synonymes typedef struct date tdate; typedef tdate * ptdate; */

Suggestion de corrig chapitre 14 exercice 1

#include <stdio.h> int main (int argc, char *argv[], char **envp) { tdate dat; ptdate ptd=&dat; /* saisie de la date */ printf (" Entrez une date ( jj mm aaaa ) :"); scanf ("%d %d %d", &dat.jour, &dat.mois, &dat.annee); /* impression de la date */ printf (" La date est : %d\t%d\t%d\n", dat.jour, dat.mois, dat.annee); /* impression de la date avec le pointeur */ printf (" La date est : %d\t%d\t%d\n", ptd->jour, ptd->mois, ptd->annee); return 0;

Donnes en entre
01 04 2003

Donnes crites sur le fichier standard de sortie


Entrez une date ( jj mm aaaa ) : La date est : 1 4 2003 La date est : 1 4 2003

c Christian Bac 1985-2003

CHAPITRE 14.

TYPES SYNONYMES ET COMPLEXES

161

14.4.2 Exercice 2
Dnir un type correspondant la dnition suivante : Une union pouvant contenir :  un tableau de 10 pointeurs sur des entiers,  un tableau de 10 pointeurs sur des ottants,  un tableau de 10 entiers,  un tableau de 10 ottants.

14.4.3 Exercice 3
Cet exercice a pour but de manipuler le remplissage d'un tableau de structures date et de permettre son dition, partir d'un menu en utilisant l'appel de fonction travers des pointeurs. Pour cela il faut crire trois fonctions :  une fonction de saisie,  une fonction de consultation,  une fonction de permettant de sortir de l'application. La fonction

main()

contient une boucle innie donnant un menu qui ore le choix entre saisie

d'une structure, dition et arrt.

c Christian Bac 1985-2003

162

14.4. EXERCICES SUR LES DCLARATIONS COMPLEXES

Programme 14.2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33

/* declaration des differents types de tableaux */ typedef int int_10[10]; typedef int *ptint_10[10]; typedef float float_10[10]; typedef float *ptfloat_10[10]; /* definition des differents objets pouvant etre contenus dans l'union */ union u1 { int_10 o1; ptint_10 o2; float_10 o3; ptfloat_10 o4; }; /* definition du type union */ typedef union u1 utab; /* definition d'un objet de ce type */ utab my_union ; #include <stdio.h> int main (int argc, char *argv[], char **envp){ int i; /* initialisation des entiers avec leur rang */ for(i=0; i < 5;i++ ) my_union.o1[i] = i; /* impression du tableau */ for(i=0; i < 5;i++ ) printf("my_union.o1[%d] = %d \n", i, my_union.o1[i]); /* initialisation des pointeurs avec leurs propres adresses */ for(i=0; i < 5;i++ ) my_union.o2[i] = & my_union.o1[i]; /* impression du tableau de pointeurs */ for(i=0; i < 5;i++ ) printf("my_union.o2[%d] = %x \n", i, my_union.o2[i]); return 0; }

Suggestion de corrig chapitre 14 exercice 2

Donnes crites sur le fichier standard de sortie


my_union.o1[0] my_union.o1[1] my_union.o1[2] my_union.o1[3] my_union.o1[4] my_union.o2[0] my_union.o2[1] my_union.o2[2] my_union.o2[3] my_union.o2[4] = = = = = = = = = = 0 1 2 3 4 80495a0 80495a4 80495a8 80495ac 80495b0

c Christian Bac 1985-2003

CHAPITRE 14.

TYPES SYNONYMES ET COMPLEXES

163

Programme 14.3 Suggestion de corrig chapitre 14 exercice 3 chier d'inclusion


1 2 3 4 5 6 7 struct date { int jour, mois, annee; };

void saisie(struct date *); void edition(struct date *); void sortie();

Programme 14.4 Suggestion de corrig chapitre 14 exercice 3 fonctions


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #include <stdio.h> #include "c14c03.h"

void saisie(struct date * ptd) { int i; /* rang dans le tableau de dates */ printf(" Entrez le rang dans le tableau date :"); scanf("%d", &i); ptd += i; /* saisie de la date */ printf(" Entrez une date ( jj mm aaaa ) :"); scanf("%d%d%d", &ptd->jour, &ptd->mois, &ptd->annee); } void edition(struct date * ptd) { int i; /* rang dans le tableau de dates */ printf("Entrez le rang dans le tableau date :"); scanf("%d", &i); ptd += i; /* edition de la date */ printf("Date dans le tableau :"); printf("%d %d %d\n", ptd->jour, ptd->mois, ptd->annee); } void sortie() { exit(0); }

c Christian Bac 1985-2003

164

14.4. EXERCICES SUR LES DCLARATIONS COMPLEXES

Programme 14.5

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

#include <stdio.h> #include "c14c03.h"

Suggestion de corrig chapitre 14 exercice 3

static struct date dat[10]; int main (int argc, char *argv[], char **envp) { int i; static void (*f[3])() = { saisie, edition, sortie }; for(;;) { printf("\tsaisie\t1\n"); printf("\tedition\t2\n"); printf("\tarret\t3\n"); printf("Choix :"); scanf("%d",&i); f[i-1](dat); /* on peut aussi ecrire : (*f[i-1])(dat); */ }

Donnes en entre
1 1 1 4 2003 2 1 1 2 12 08 1998 3

Donnes crites sur le fichier standard de sortie


saisie 1 edition 2 arret 3 Choix : Entrez le rang dans le tableau date : Entrez une date ( jj mm aaaa ) : saisie 1 edition 2 arret 3 Choix :Entrez le rang dans le tableau date :Date dans le tableau :1 4 2003 saisie 1 edition 2 arret 3 Choix : Entrez le rang dans le tableau date : Entrez une date ( jj mm aaaa ) : saisie 1 edition 2 arret 3 Choix :

c Christian Bac 1985-2003

Chapitre 15

Prprocesseur
Comme nous l'avons dit dans la section 1.4, le pr-processeur ou pr-compilateur (alias C Pre Processor ou CPP) traite le chier source avant le compilateur. Il ne manipule que des chanes de caractres. Il retire les parties commentaires (entre /* et */). Il prend en compte les lignes commenant par un # pour crer le code que le compilateur analysera. Ses possibilits sont de 4 ordres :  inclusion de chier en utilisant la directive  dnition de variables de prcompilation :  

#include

#define NOM valeur #undef NOM

 dnition de macro-fonction ou macro-expression :

#define m(x) (128*(x)+342*(x)*(x))

 slection du code en fonction des variables du pr-processeur :     

#if #ifdef #ifndef #else #endif

15.1 Commentaires
Les commentaires sont destins faciliter la comprhension du source lors de la relecture. Ils ne sont d'aucune utilit au compilateur, et il est naturel qu'ils n'apparaissent pas dans le source qui lui est destin. Le pr-processeur retire les caractres compris entre /* et */. Il ne gre pas les imbrications de commentaires. La mise en commentaire d'une section source peut alors crer des erreurs de compilation comme le montre le programme 15.2. Le tableau 15.1 montre le retrait des commentaires dans un chier source avant le passage vers le compilateur. La gure15.2 montre le retrait des commentaires dans un chier source aprs l'introduction du nouveau commentaire ce qui provoque une erreur de syntaxe sur la ligne voit

*/ a = 2 ;.

a = 2 ; car le compilateur

15.2 Inclusion de chiers


L'inclusion de chiers par le pr-processeur est dclenche par la rencontre de la directive : c Christian Bac 1985-2003

166

15.2.

INCLUSION DE FICHIERS

Programme 15.1

1 2 3 4 5 6 7 8 9 10 11 12

int main (int argc, char *argv[]) { int a,b,c; a=1; b=1; c=1; /* ajout a+b a c */ c += a +b ; a=2; return 0; }

Traitement des commentaires

Source aprs prcompilation


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 # 1 "c15e01.c" # 1 "<interne>" # 1 "<ligne de commande>" # 1 "c15e01.c" int main (int argc, char *argv[]) { int a,b,c; a=1; b=1; c=1; c += a +b ; a=2; return 0;

#include nom_de_fichier
Par convention, les chiers inclure ont des noms termins par  .h pour signier header. Il existe trois faons de nommer un chier inclure. Ces faons dterminent l'endroit o le pr-processeur cherche le chier. 1. par son chemin absolu, ce qui se traduit dans un systme de type UNIX par le fait que le nom de chemin correspondant au chier commence par / ;     

#include "/users/chris/essai/header.h" #include < /users/chris/essai/header.h > #include "header.h" #include "h/mem.h" #include "../h/uucp.h"

2. partir du catalogue courant, si le nom de chier est entour par des guillemets ;

3. partir d'un catalogue prdni correspondant l'installation du compilateur, si le nom de chier est entour par un infrieur et un suprieur. Ce catalogue est de manire standard 

/usr/include dans les systmes #include < stdio.h >  #include < sys/dir.h >

UNIX.

Il est possible de demander au pr-processeur d'ajouter d'autres catalogues sa recherche, en utilisant une option de compilation l'appel de l'en-chaneur de passes. Cette option est dans un c Christian Bac 1985-2003

CHAPITRE 15.

PRPROCESSEUR

167

Programme 15.2

1 2 3 4 5 6 7 8 9 10 11 12 13 14

int main (int argc, char *argv[]) { int a,b,c; a=1; b=1; /* Ceci ne nous interesse plus c=1; /* ajout a+b a c */ c += a +b ; */ a=2; return 0; }

Erreur due au traitement des commentaires

Source aprs prcompilation


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 # 1 "c15e02.c" # 1 "<interne>" # 1 "<ligne de commande>" # 1 "c15e02.c" int main (int argc, char *argv[]) { int a,b,c; a=1; b=1;

c += a +b ; */ a=2; return 0;

en-chaneur de passe UNIX

-Inom_du_catalogue. Cette option peut tre utilise plusieurs fois de

manire spcier plusieurs catalogues de recherche. Lorsque le chier inclure est spci entre guillemets, le pr-processeur cherche le chier : 1. dans le catalogue courant, 2. puis dans les catalogues spcis par les options

-I.

Si le nom du chier include est entre  < et  >, le pr-processeur cherche le chier : 1. dans les catalogues spcis par les options

-I,

2. puis dans le catalogue par dfaut du compilateur. Les chiers inclus sont traits par le pr-processeur. Ils peuvent contenir d'autres inclusions de chiers. c Christian Bac 1985-2003

168

15.3. VARIABLES DE PR-COMPILATION

Sans constante de prcompilation

Avec constante de prcompilation

int tab[20] for ( i = 0 ; i < 20 ; i++ )

#define LG 20 int tab[LG] for ( i = 0 ; i < LG ; i++ )

Tab.

15.1  Utilisation d'une constante de compilation

15.3 Variables de pr-compilation


Les variables de pr-compilation ont deux utilisations :  la dnition de constantes utilises pour la compilation ;  la dnition de variables qui jouent un rle de boolen et permettent la slection du code.

15.3.1 Dnition de constantes de compilation


Comme le montre la table 15.1, l'usage le plus courant des constantes de compilation est associ la manipulation de tableaux. Il est plus simple et plus sr d'avoir une constante qui soit utilise lors de la dnition et lors de la manipulation du tableau. La dnition d'une constante de prcompilation se fait par :

#define nom_de_la_variable valeur


Ceci vite de rechercher dans le source les instructions qui font rfrence la taille du tableau lorsque cette taille change. Lorsqu'une constante de compilation a t dnie, CPP change toutes les occurrences du nom de la constante par sa valeur, sauf lorsque le nom se trouve dans une chane de caractres. Le changement ne se fait que lorsque le nom de la variable est isol. Le tableau 15.3 est un exemple d'utilisation des variables de prcompilation.

15.3.2 Dnition destine la slection


CPP permet de dnir des variables de prcompilation qui permettent de raliser les tests de slection de parties de chier source. Ces variables n'ont pas besoin d'tre associes une valeur. Elles jouent en quelque sorte le rle de boolens puisque le prcompilateur teste si elles sont dnies ou non. Elles servent dterminer les parties de codes compiler comme nous le verrons dans la section 15.7.

#define nom_de_la_variable

La dnition d'une variable de prcompilation se fait par :

15.4 Dnition de macro-expressions


CPP permet la dnition de macro-expressions encore appeles macro-fonctions. Ces macroexpressions sont trs semblables celles de macro-assembleurs. La dnition d'une macro-expression se fait aussi par la directive dnition du corps de la macro.

#define. Le nom de la macro

est suivi d'une parenthse ouvrante, de la liste des arguments, d'une parenthse fermante, et de la

#define add(x1,x2) ((x1) += (x2))


Lorsque le prprocesseur rencontre une expression du type

add(a,b), il gnre ((a) += (b)).

Il faut faire attention l'ordre d'valuation pour des macro-expressions complexes, et la technique la plus simple est l'utilisation intensive du parenthsage en encadrant les noms des pseudoc Christian Bac 1985-2003

CHAPITRE 15.

PRPROCESSEUR

169

Programme 15.3

1 2 3 4 5 6 7 8 9 10 11 12

#define PI 3.14159 #define LG 20

Interprtation des variables par le prprocesseur

int main (int argc, char *argv[]) { int i,t[LG]; for (i=0; i<LG; i++){ printf("Valeur de PI \%d",t[i] = PI); } return 0; }

Source aprs prcompilation


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 # # # # 1 1 1 1 "c15e03.c" "<interne>" "<ligne de commande>" "c15e03.c"

int main (int argc, char *argv[]) { int i,t[20]; for (i=0; i<20; i++){ printf("Valeur de PI \%d",t[i] = 3.14159); } return 0; }

variables par des parenthses mais aussi en encadrant la macro-expression elle-mme. Comme le montre l'exemple 15.4, le parenthsage garantit que l'expression rsultante est correctement interprte, la ligne 16 de l'exemple montre que l'expression

m(a+b)

est mal value.

15.5 Eacement d'une dnition


#undef nom_de_la_variable
Il est possible d'eacer une dnition de variable par : La variable est alors considre comme non dnie. Dans le cas o la variable est associe une valeur, les occurrences de son nom ne sont plus remplaces par sa valeur.

15.6 Dnition l'appel de l'enchaneur de passes


Il existe deux possibilits pour dnir les variables de prcompilation l'appel de l'enchaneur de passes :  en utilisant l'option

trait par le prprocesseur comme si la

-Dnom avec le nom de la variable de prcompilation. variable de prcompilation nom


c Christian Bac 1985-2003

Le chier sera alors tait dnie, par la

170

15.7.

SLECTION DE CODE

directive

 en utilisant l'option

#define nom. -Dnom=valeur nom

avec le nom de la constante

de prcompilation suivi du Le prprocesseur si la constante de

signe = et de la valeur associer prcompilation

cette constante de prcompilation.

changera les occurrences de la variable

nom

par la valeur

tait dnie, par la directive

valeur, comme #define nom valeur.

Il existe des variables de prcompilation qui sont prdnies. Elles sont associes au type de la machine, au compilateur et l'environnement. Elles sont la plupart du temps d'une part xes par la compilation de l'enchaneur de passe lui-mme ou par la dtection de de l'environnement par ce dernier. Par exemple, sur un PC au 05/04/2003 les variables suivantes sont prdnies par l'enchaneur de passes :

__ELF__ unix __gnu_linux__ linux i386 __i386 __i386__


L'utilisation de l'option d'autres. Pour nir, les compilateurs la norme ANSI doivent avoir une variable de prprocesseur prdnie appele

dumpspecs

avec

gcc

ou

cpp

donne ces informations parmi beaucoup

__STDC__.

Il est possible d'eacer ces dnitions au niveau de l'appel l'enchaneur de passes, en utilisant l'option

-Unom.

Ceci ne peut pas inhiber les dnitions qui apparaissent dans le code par des

#define.

15.7 Slection de code


La slection de code permet de gnrer partir d'un mme chier source des chiers excutables qui se comportent diremment. Cela permet en particulier de partir des mme chiers sources pour obtenir : des binaires excutables pour des machines et des systmes dirents, ou des environnements d'excution dirents. Cela permet aussi d'avoir un source avec des instructions qui donnent des informations sur les variables (traces), et pouvoir gnrer le chier excutable avec ou sans ces traces. Le principe de base consiste passer ou supprimer des parties de code suivant des conditions xes partir des variables de prcompilation. La slection se fait partir des lignes de directives suivantes :     

#if #ifdef #ifndef #else #endif

Toute condition de slection de code commence par un avec ventuellement une partie

#else.

#if[n[def]], et se termine par #endif, #if[n[def]] et le #else est pass #else et le #endif. S'il n'y a pas

Lorsque la condition est vraie, le code qui se trouve entre le de partie

au compilateur. Si elle est fausse, le code pass est celui entre le

#else

aucun code n'est pass. c Christian Bac 1985-2003

CHAPITRE 15.

PRPROCESSEUR

171

15.7.1 Slection avec #if


La slection avec

#if

se fait par test d'une expression valide du langage

C. Cette expression

ne peut mettre en jeu que des constantes et des variables de prcompilation. Le programme 15.5 quelques exemples d'utilisaiton de

#if.

En plus des expressions du langage C, le prprocesseur permet de tester l'existence d'une variable en utilisant le mot

defined

dans la ligne de test.

#define DEBUG #if defined DEBUG code passe #endif #if defined(DEBUG) code passe #endif

15.7.2 Slection avec #ifdef et #ifndef


La slection avec Dans le programme 15.6 extrait du logiciel libre De plus le type de retour de la fonction

#ifdef et #ifndef est semblable celle avec #if defined ou #if !defined. sendmail, le test de compilation avec LOG permet xalloc()
dpend du fait que le compilateur soit du

de dterminer si des informations sont envoyes au systme de trace du systme d'exploitation. type standard ANSI ou non. Comme le montre le programme 15.7, lui aussi extrait du code de

sendmail,

les slections peuvent tre imbriques.

15.8 Exercices sur le prprocesseur


15.8.1 Exercice 1
Dnir les macros fonctions suivantes :  valeur absolue d'une expression,  minimum de deux expressions,  maximum de deux expressions,  minimum de trois expressions,  maximum de trois expressions,  minimum en valeur absolue de deux expressions (en utilisant valeur absolue d'une expression et en ne l'utilisant pas),  maximum en valeur absolue de trois expressions (en utilisant valeur absolue d'une expression et en ne l'utilisant pas), Utiliser ces dnitions pour faire imprimer leurs rsultats sur des entiers puis des ottants entrs au clavier. Utiliser les options -E ou -P de l'enchaineur de passes pour lire le programme C gnr.

15.8.2 Exercice 2
Reprendre l'exercice sur le calcul des racines d'une quation du second degr, pour ajouter des lignes de debug imprimant la valeur du discriminant et les calculs intermdiaires. Ces lignes doivent se trouver dans des test du prprocesseur de manire n'tre prsente que lorsqu'on passe l'option -DDEBUG la compilation. c Christian Bac 1985-2003

172

15.8.

EXERCICES SUR LE PRPROCESSEUR

Le chier d'inclusion est identique celui du programme 9.8 et les fonctions sont les mmes que dans le programme 9.6.

c Christian Bac 1985-2003

CHAPITRE 15.

PRPROCESSEUR

173

Programme 15.4

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

Evaluation de macros par CPP

#define add(x1,x2) ((x1) += (x2)) #define m(x) 128*x+342*x*x #define y(x) (128*(x)+342*(x)*(x)) int main (int argc, char *argv[]) { int a,b,c; int e,f,g; a = b = c = 1; d = e = f = 2; add(a,b); add(a,b+1); d = m(a); e = y(a); d = m(a+b); d = y(a+b); f = m(add(a,b)); f = y(add(a,b)); return 0; }

Source aprs prcompilation


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 # # # # 1 1 1 1 "c15e04.c" "<interne>" "<ligne de commande>" "c15e04.c"

int main (int argc, char *argv[]) { int a,b,c; int e,f,g; a = b = c = 1; d = e = f = 2; ((a) += (b)); ((a) += (b+1)); d = 128*a+342*a*a; e = (128*(a)+342*(a)*(a)); d = 128*a+b+342*a+b*a+b; d = (128*(a+b)+342*(a+b)*(a+b)); f = 128*((a) += (b))+342*((a) += (b))*((a) += (b)); f = (128*(((a) += (b)))+342*(((a) += (b)))*(((a) += (b)))); return 0; }

c Christian Bac 1985-2003

174

15.8.

EXERCICES SUR LE PRPROCESSEUR

Programme 15.5

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

#define vrai 1 #define faux 0 #if vrai vrai_est_vrai #else vrai_est_faux #endif #if faux faux_est_vrai #else faux_est_faux #endif #if vrai || faux vrai_ou_faux_est_vrai #endif #if !faux not_faux_est_vrai #endif #if vrai && !faux vrai_et_not_faux_est_vrai #endif

Exemple d'utilisation du #if

Source aprs prcompilation


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 # # # # 1 1 1 1 "c15e05.c" "<interne>" "<ligne de commande>" "c15e05.c"

vrai_est_vrai

faux_est_faux vrai_ou_faux_est_vrai not_faux_est_vrai vrai_et_not_faux_est_vrai

c Christian Bac 1985-2003

CHAPITRE 15.

PRPROCESSEUR

175

Programme 15.6 Exemples de slection de code par #ifdef


#ifdef LOG if (LogLevel > 20) syslog(LOG_DEBUG, "%s: unlink %s", CurEnv->e_id, f); #endif /* LOG */ #ifdef __STDC__ void * #else /* !__STDC__ */ char * #endif /* __STDC__ */ xalloc(sz) register int sz; { #ifdef __STDC__ register void *p; #else /* !__STDC__ */ register char *p; #endif /* __STDC__ */

Programme 15.7 Slection de code par #ifdef imbriqus


#ifdef _PATH_SENDMAILPID void WritePid() { extern char *PidFile; FILE *f;

(void) unlink(PidFile); /* try to be safe :-) */ if ((f = dfopen(PidFile, "w")) != NULL) { fprintf(f, "%d\\n", getpid()); (void) chmod(PidFile, 0444); (void) fclose(f); } # ifdef LOG else syslog(LOG_NOTICE, "Could not log daemon " "pid %d to file %s: %m", getpid(), PidFile); # endif /* LOG */ } #endif /* _PATH_SENDMAILPID */

c Christian Bac 1985-2003

176

15.8.

EXERCICES SUR LE PRPROCESSEUR

Programme 15.8 Suggestion de corrig chapitre 15 exercice 1 dnition des macros


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #define #define #define #define abs(a) ((a) < 0 ? (-(a)) : (a)) min(a1,a2) ((a1) < (a2) ? (a1) : (a2)) max(a1,a2) ((a1) > (a2) ? (a1) : (a2)) min3(a1,a2,a3) ((a1) < (a2) ? (a1) < (a3) ? (a1) (a2) < (a3) ? (a2) : (a3)) #define max3(a1,a2,a3) ((a1) > (a2) ? (a1) > (a3) ? (a1) (a2) > (a3) ? (a2) : (a3)) #define min_abs(a1,a2) (min(abs(a1),abs(a2))) #define max_abs2(a1,a2) \ (((a1) > 0 && (a2) > 0) ? ((a1) > (a2) ? (a1) : (a2)) (((a1) < 0 && (a2) > 0) ? ((-(a1)) > (a2) ? (-(a1)) : (((a1) > 0 && (a2) < 0) ? ((-(a2)) > (a1) ? (-(a2)) : ((-(a2)) > (-(a1)) ? (-(a2)) : (-(a1))))))

: (a3) : \ : (a3) : \

: \ (a2)) : \ (a1)) : \

#define max_abs2bis(a1,a2) \ (((a1) < 0 ? -(a1) : (a1)) > ((a2) < 0) ? (-a2) : (a2)) ? \ (((a1) < 0 ? -(a1) : (a1)) : ((a2) < 0) ? (-a2) : (a2)) #define max_abs3(a1,a2,a3) max3(abs(a1),abs(a2),abs(a3))

c Christian Bac 1985-2003

CHAPITRE 15.

PRPROCESSEUR

177

Programme 15.9

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

#include <stdio.h> #include "c15c01.h"

Suggestion de corrig chapitre 15 exercice 1

int main (int argc, char *argv[], char **envp) { int i,j,k; printf("Rentrez les valeurs de i j et k :"); scanf("%d%d%d",&i,&j,&k); printf("Valeurs printf("Minimum printf("Maximum printf("Minimum printf("Maximum printf("Minimum printf("Maximum printf("Maximum return 0; absolues : %d %d %d \n", abs(i), abs(j), abs(k)); i et j : %d \n", min(i,j)); i et k : %d \n", max(i,k)); i j et k : %d \n", min3(i,j,k)); i j et k : %d \n", max3(i,j,k)); des valeurs absolues : %d \n", min_abs(i,j)); des valeurs absolues : %d \n", max_abs2(i,j)); des trois en valeur absolue : %d \n",max_abs3(i,j,k));

Donnes en entre
12 -23 7

Donnes crites sur le fichier standard de sortie


Rentrez Minimum Maximum Minimum Maximum Minimum Maximum Maximum les valeurs de i j et k :Valeurs absolues : 12 23 7 i et j : -23 i et k : 12 i j et k : -23 i j et k : 12 des valeurs absolues : 12 des valeurs absolues : 23 des trois en valeur absolue : 23

c Christian Bac 1985-2003

178

15.8.

EXERCICES SUR LE PRPROCESSEUR

Programme 15.10 Suggestion de corrig chapitre 15 exercice 2


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53

#include <stdio.h> #include <math.h> #include "c09c03a.h" int main (int argc, char *argv[], char **envp){ float a,b,c,r,r1; double rdis; float res; printf("calcul des racines de ax2 + bx + c\n\n"); /* saisie des coefficients */ printf("saisissez les coefficients a b et c\n"); scanf("%f %f %f",&a,&b,&c); if( a == 0 ){ printf(" Equation du premier degre \n"); printf(" La solution est x = %f \n", -c / b); exit(0); } r = -b/(2 * a); #ifdef DEBUG printf(" -b/2*a : %f \n", r); #endif res = dis(a,b,c); #ifdef DEBUG printf(" discriminant : %f \n", res); #endif switch ( res < 0 ? -1 : (res >0 ? 1 : 0 )) { case 1: rdis = sqrt(res); #ifdef DEBUG printf(" racine du discriminant : %f \n", rdis); #endif r1 = rdis / ( 2 * a); #ifdef DEBUG printf(" r1 : %f \n", r1); #endif rac2(r,r1); break; case -1: rdis = sqrt(-res); #ifdef DEBUG printf(" racine du discriminant : %f \n", rdis); #endif r1 = rdis / ( 2 * a); #ifdef DEBUG printf(" r1 : %f \n", r1); #endif complex(r,r1); break; case 0: racd(r); break; } return 0; }
c Christian Bac 1985-2003

Chapitre 16

Entres-sorties de la bibliothque
Comme nous l'avons vu, le langage C est de bas niveau. Pour permettre aux programmeurs de raliser des programmes sans tre oblig de rinventer les fonctionalits les plus courantes, la bibliothque du langage C fournit des fonctions de plus haut niveau ainsi que des fonctions qui permettent la ralisation des entre-sorties. La bibliothque standard contient : 1. des fonctions permettant la gestion des entres-sorties (E/S) ; 2. des fonctions de manipulation de chanes de caractres ; 3. des fonctions d'allocation dynamique de mmoire ; 4. des fonctions caractre gnral qui permettent l'accs au systme. L'ensemble des fonctions qui permettent de faire des entre-sorties standards de bas niveau est appell BIO (Basic Input Output). Ces fonctions et les structures associes sont dcrites dans le

< stdio.h >. Tout programme #include<stdio.h> Le chier stdio.h contient :


chier  les prototypes des fonctions ;  les dnitions de constantes :

dsirant manipuler les E/S devra contenir la ligne :

 les dnitions de macro-expressions ;

EOF, stdin, stdout,

...;

 la dnition du tableau des chiers ouverts.

Le langage C donne une vision "UNIXienne " des entre-sorties. En langage C, un chier est une suite d'octets (un caractre = 1 octet). Le chier n'a pas de structure propre qui lui est attache. Il est cependant possible au niveau programme de considrer un chier comme une suite d'enregistrements correspondant une structure. Le principe de la manipulation d'un chier est le suivant : 1. ouverture du chier ; 2. lecture, criture, et dplacement dans le chier ; 3. fermeture du chier.

16.1 Entre-sorties standards


Conformment la vision UNIXienne des entres-sorties, trois pseudo-chiers sont ouverts par l'environnement de programmation lorsque le programme commence s'excuter. Ces trois pseudo-chiers permettent l'accs au terminal de l'utilisateur. Ils ont pour nom : c Christian Bac 1985-2003

180

16.1. ENTRE-SORTIES STANDARDS

stdin

pour chier standard d'entre ; ce chier est le plus souvent associ au clavier ; pour chier de standard sortie ; ce chier dsigne le plus souvent l'cran et les fonctions

stdout

d'accs associes utilisent une technique de tampon

1 pour les critures qui lui sont associes ;

stderr

pour chier standard d'erreur, ce chier correspond lui aussi le plus souvent l'cran mais

les critures sont non tamponnes. Ces chiers peuvent tre redirigs au niveau de l'interprte de commandes [Bou78] par l'utilisation des symboles

>

et

<

l'appel du programme. Ils sont automatiquement redirigs lorsque

les commandes sont enchanes par des tubes en utilisant le symbole non exaustifs d'utilisation des redirections :

|.

Voici quelques exemples

prog >fichier : lorsque prog crit, les octets sont dirigs vers le chier fichier prog <fichier : prog lit dans le chier fichier prog 2 >fichier : prog crit ses messages d'erreur dans le chier fichier prog1 | prog2 : la sortie standart de prog1 est associe l'entre standard de prog2.
ces chiers standards sont associes des fonctions prdnies qui permettent de raliser les oprations suivantes :  lecture et criture caractre par caractre ;  lecture et criture ligne par ligne ;  lecture et criture formates.

16.1.1 changes caractre par caractre


Dans ces changes, l'unit de base est le caractre que le systme considre comme un octet parfois rduit une version de l'ASCII sur sept bits. Les deux fonctions que nous prsentons ici sont souvent des macro-expressions du prprocesseur (voir chapitre 15) ; nous les considrerons comme des fonctions pour simplier la prsentation.

int getchar(void) ;

synopsis :

cette fonction permet de lire un caractre sur

est considr comme tant du type

unsigned char ;

stdin s'il

y en a un. Ce caractre

argument : aucun ; retour : la fonction retourne un entier


de chier (EOF).

pour permettre la reconnaissance de la valeur n

L'entier contient soit la valeur du caractre lu soit en n de chier la fonction retourne la valeur

EOF ;

conditions d'erreur :
int putchar(int ) ;

EOF.

synopsis : cette fonction permet d'crire un caractre sur stdout ; argument : Elle est dnie comme recevant un entier2 pour tre conforme getchar().
Ceci permet d'crire

putchar(getchar()).

retour : Elle retourne la valeur du caractre crit toujours considr comme un entier. conditions d'erreur : en cas d'erreur la fonction retourne EOF.
Le programme 16.1 ralise la lecture de son chier standard d'entre caractre par caractre et reproduit les caractres de son chier standard d'entre sur son chier standard de sortie. Son rle est similaire celui de l'utilitaire

cat(1)

du systme UNIX lorsqu'il est utilis comme ltre.

1 Souvent 2 Avant

nomm par l'anglicisme buer, ce tampon permet de ne pas trop solliciter le systme d'exploitation

lors des critures. Sa taille la plus courante est un kilo-octets. la norme C99, la promotion implicite des arguments de fonctions (voir 3.8.1) faisait que de toute faon la valeur d'un caractre tait convertie en une valeur d'entier lors du passage d'arguments une fonction.

c Christian Bac 1985-2003

CHAPITRE 16.

ENTRES-SORTIES DE LA BIBLIOTHQUE

181

standards
1 2 3 4 5 6 7 8 9

Programme 16.1

Lecture et criture caractre par caractre sur les fichiers

#include <stdio.h> int main (int argc, char *argv[]) { int c; while ((c = getchar ()) != EOF) putchar (c); return 0; }

Donnes en entre
The quick brown fox jumped over the lazy dog, 1234567890.

Donnes crites sur le fichier standard de sortie


16.1.2 changes ligne par ligne

The quick brown fox jumped over the lazy dog, 1234567890.

Dans ces changes, l'unit de base est la ligne de caractres. La ligne est considre comme une suite de caractres l'abrviation

char

termine par un caractre de n de ligne ou par la dtection de la

n du chier. Le caractre de n de ligne a une valeur entire gale 10 et est reprsent par

'\n'.

char *gets(char *) ;

synopsis :
nul

lire une ligne sur stdin ; les caractres de la ligne sont rangs (un caractre par en argument la fonction. Le mmoire, puisse tre utilise

octet) dans la mmoire partir de l'adresse donne

retour chariot est lu mais n'est pas rang en mmoire. Il est remplac par un caractre

'\0'

de manire ce que la ligne, une fois place en

comme une chane de caractres.

argument :
lus.

l'adresse d'une zone mmoire dans laquelle la fonction doit ranger les caractres

retour :

Si des caractres ont t lus, la fonction retourne l'adresse de son argument pour les appels de fonction. pointeur de caractre de valeur 0 (NULL dni dans l'appel (aucun caractre

permettre une imbrication dans

conditions d'erreur :
< stdio.h >).

Si la n de chier est atteinte, lors de

n'est lu), la fonction retourne un

remarque :

Cette fonction ne peut pas vrier que la taille de la ligne lue est infrieure

la taille de la zone mmoire dans laquelle il lui est demand de placer les caractres. Il faut lui prfrer la fonction

fgets()

pour tout logiciel de qualit.

int puts(char *) ;

synopsis : criture d'une chane de caractres, suivie d'un retour chariot sur stdout. argument : l'adresse d'une chane de caractres. retour : une valeur entire non ngative en cas de succs. conditions d'erreur : Elle retourne la valeur EOF en cas de problme.

La version 16.2 reprend le programme prcdent de lecture et rcriture entre le chier standard d'entre et le chier standard de sortie mais ralise ces entres-sorties ligne par ligne. Le choix d'un c Christian Bac 1985-2003

182

16.1. ENTRE-SORTIES STANDARDS

tableau de 256 caractres permet d'esprer qu'aucune ligne lue ne provoquera un dbordement par la fonction

gets().

Ceci reste un espoir et peut tre dmenti si le programme est confront

une ligne de plus grande taille, dans ce cas le comportement du programme est non dni .

Programme 16.2

1 2 3 4 5 6 7 8 9

#include <stdio.h> int main (int argc, char *argv[]) { char BigBuf[256]; while (gets (BigBuf) != NULL) puts (BigBuf); return 0; }

Lecture ligne par ligne sur les fichiers standards

Donnes en entre
The quick brown fox jumped over the lazy dog, 1234567890.

Donnes crites sur le fichier standard de sortie

The quick brown fox jumped over the lazy dog, 1234567890.

16.1.3 changes avec formats


Nous avons dj parl des entre-sorties formates dans le chapitre sur les lments de base permettant de dbuter la programmation (chapitre 4). Les fonctions permettant de faire des entresorties formates sur les chiers standards d'entre et de sortie sont les suivantes :

int scanf(const char *, ...) ;

synopsis : lecture formate sur stdin. arguments : comme l'indique la spcication  ...,
guments variable partir du second argument. des variables saisir.

cette fonction accepte une liste d'ar-

1. le premier argument est une chane de caractres qui doit contenir la description

2. les autres arguments sont les adresses des variables (conformment la description donne dans le premier argument) qui sont aectes par la lecture.

retour : nombre de variables saisies. conditions d'erreur : la valeur EOF


standard ferm.

est retourne en cas d'appel sur un chier d'entre

int printf(const char *, ...) ;

synopsis : criture formate sur stdout arguments : chane de caractres contenant des commentaires et
ments crire, suivie des valeurs des variables.

des descriptions d'argu-

retour : nombre de caractres crits. conditions d'erreur : la valeur EOF est retourne
standard ferm.

en cas d'appel sur un chier de sortie

3 Cette

fonction est l'un des points faibles des programmes crits en langage C face une attaque de type

dbordement de buer, l'utilisation de doit lui tre prfre.

fgets@A

que nous verrons plus loin et qui permet d'viter ces dbordements

c Christian Bac 1985-2003

CHAPITRE 16.

ENTRES-SORTIES DE LA BIBLIOTHQUE

183

Des exemples de formats sont donns dans le tableau 4.2. Les possibilits en matire de format sont donnes de manire exhaustive dans la partie sur les entre-sorties formates (voir section 16.5).

16.2 Ouverture d'un chier


part les trois pseudo-chiers dont nous avons parl dans le paragraphe prcdent, tout chier doit tre ouvert avant de pouvoir accder son contenu en lecture, criture ou modication. L'ouverture d'un chier est l'association d'un objet extrieur (le chier) au programme en cours d'excution. Une fonction d'ouverture spcie le nom du chier l'intrieur de l'arborescence du systme de chiers et des attributs d'ouverture. L'ouverture d'un chier est ralise par la fonction

fopen()

selon la description suivante :

FILE *fopen(const char *, const char* ) ;

synopsis :

ouverture d'un chier rfrenc par le premier argument

(nom du chier dans

le systme de chiers sous forme d'une chane de caractres) selon le mode d'ouverture dcrit par le second argument (chane de caractres).

arguments :
1. la premire chane de caractres contient le nom du chier de manire rfrencer le chier dans l'arborescence. Ce nom est dpendant du systme d'exploitation dans lequel le programme s'excute. 2. Le deuxime argument est lui aussi une chane de caractres. Il spcie le type d'ouverture.

retour :

pointeur sur un objet de type

FILE

(type dni dans

< stdio.h >)

qui sera utilis

par les oprations de manipulation du chier ouvert (lecture, criture ou dplacement).

conditions d'erreur :

le pointeur

NULL ((void *)0)

est retourn si le chier n'a pas pu

tre ouvert (problmes d'existence du chier ou de droits d'accs). Le type d'ouverture est spci partir d'un mode de base et de complments. Sans prcision, le chier est considr comme une chier de type texte (c'est--dire qu'il ne contient que des caractres ASCII). Le type d'ouverture de base peut tre :

"r" "w" "a"

le chier est ouvert en lecture.

Si le chier n'existe pas, la fonction ne le cre pas. Si le chier n'existe pas, la fonction le cre. Si le chier

le chier est ouvert en criture. existe la fonction le vide.

le chier est ouvert en ajout. Si le chier n'existe pas, la fonction le cre. Les critures auront lieu la n du chier.

Le type d'ouverture peut tre agrment de deux caractres qui sont :

"b" "+"

le chier est considr en mode binaire. Il peut donc contenir des donnes qui sont transfres sans interprtation par les fonctions de la bibliothque. le chier est ouvert dans le mode complmentaire du mode de base. Par exemple s'il est ouvert dans le mode "r+" cela signie qu'il est ouvert en mode lecture et plus, soit lecture et criture.

La combinaison des modes de base et des complments donne les possibilits suivantes :

"r+" "w+"

le chier est ouvert en lecture plus criture.

Si le chier n'existe pas, la fonction ne le cre

pas. Le chier peut tre lu, modi et agrandi. le chier est ouvert en criture plus lecture. Si le chier n'existe pas, la fonction le cre. Si le chier existe, la fonction le vide. Le chier peut tre manipul en criture et relecture.

c Christian Bac 1985-2003

184

16.3.

FERMETURE D'UN FICHIER

"a+" "rb" "wb" "ab"

le chier est ouvert en ajout plus lecture.

Si le chier n'existe pas, la fonction le cre.

Les

critures auront lieu la n du chier. Le chier peut tre lu. le chier est ouvert en lecture et en mode binaire. Si le chier n'existe pas, la fonction ne le cre pas. le chier est ouvert en criture et en mode binaire. cre. Si le chier existe, la fonction le vide. Si le chier n'existe pas, la fonction le

le chier est ouvert en ajout et en mode binaire. Si le chier n'existe pas, la fonction le cre. Les critures auront lieu la n du chier.

"r+b" "w+b" "a+b"

ou

"rb+"le "wb+"

chier est ouvert en lecture plus

criture et en mode binaire.

Si le chier

n'existe pas, la fonction ne le cre pas. Le chier peut tre lu, modi et agrandi. ou le chier est ouvert en criture plus lecture et en mode binaire. Si le chier

n'existe pas, la fonction le cre. crit puis lu et crit. ou

Si le chier existe, la fonction le vide. Le chier peut tre

"ab+"le chier est ouvert en ajout plus

lecture et en mode binaire. Si le chier n'existe

pas, la fonction le cre. La fonction

Les critures auront lieu la n du chier.

fopen() retourne une rfrence vers une structure de donnes qui sert pour toutes FILE *)
doit tre dclar comme dans le programme 16.3 Si le systme

les autres oprations. Le pointeur qui reoit cette rfrence (souvent appel pointeur de chier par une traduction de

Programme 16.3 Ouverture d'un chier


1 2 3 4 5 6 7 8 9

#include <stdio.h> int main (int argc, char *argv[]) { FILE *MyFich; MyFich = fopen ("/etc/passwd", "r"); /* ... */ return 0; } NULL. Si un

d'exploitation ne peut pas ouvrir le chier, il retourne une rfrence gale au pointeur

chier qui n'existe pas est ouvert en mode criture ou ajout, il est cr par le systme.

16.3 Fermeture d'un chier


Avant d'tudier les fonctions permettant d'accder aux donnes d'un chier ouvert, considrons la fonction qui permet de terminer la manipulation d'un chier ouvert. Cette fonction ralise la fermeture du chier ouvert. Elle a le prototype suivant :

int fclose(FILE *) ;

synopsis :

c'est la fonction inverse de

la structure

FILE

fopen() ;

elle dtruit

le lien entre la rfrence vers

et le chier

physique. Si le chier ouvert est en mode criture, la

fermeture provoque l'criture physique des donnes du tampon (voir 16.7).

arguments : une rfrence de type FILE valide. retour : 0 dans le cas normal. conditions d'erreur : la fonction retourne EOF en cas d'erreur.
fopen()
Tout programme manipulant un chier doit donc tre encadr par les deux appels de fonctions et

fclose()

comme le montre la gure 16.4. c Christian Bac 1985-2003

CHAPITRE 16.

ENTRES-SORTIES DE LA BIBLIOTHQUE

185

Programme 16.4 Ouverture et fermeture d'un chier


1 2 3 4 5 6 7 8 9 10 #include <stdio.h> int main (int argc, char *argv[]) { FILE *MyFich; MyFich = fopen ("/etc/passwd", "r"); /* ... */ fclose (MyFich); return 0; }

16.4 Accs au contenu du chier


Une fois le chier ouvert, le langage C permet plusieurs types d'accs un chier :  par caractre,  par ligne,  par enregistrement,  par donnes formates. Dans tous les cas, les fonctions d'accs au chier (sauf les oprations de dplacement) ont un comportement squentiel. L'appel de ces fonctions provoque le dplacement du pointeur courant relatif au chier ouvert. Si le chier est ouvert en mode lecture, les oprations de lecture donnent une impression de consommation des donnes contenues dans le chier jusqu' la rencontre de la n du chier.

16.4.1 Accs caractre par caractre


Les fonctions suivantes permettent l'accs caractre par caractre :

int fgetc(FILE *) ;

synopsis : lecture d'un caractre (unsigned char) dans le chier associ ; argument : une rfrence de type FILE valide correspondant un chier ouvert en lecture ;

retour : la valeur du caractre lu promue dans un entier ; conditions d'erreur : la rencontre de la n de chier, la fonction retourne EOF et positionne les indicateurs associs (voir 16.8).

int getc(FILE *) ;

synopsis : synopsis :

cette fonction est identique

fgetc()

mais peut tre ralise par une macro

dnie dans

< stdio.h >.

int ungetc(int, FILE *) ;


cette fonction permet de remettre un caractre dans le buer de lecture associ un ux d'entre.

int fputc(int , FILE *) ;

synopsis :

crit dans le chier associ dcrit par le second

argument un caractre spci

dans le premier argument. Ce caractre est converti en un

argument : retour :

unsigned char ;

le premier argument contient le caractre

rfrence de type

FILE

crire et le second contient la

du chier ouvert ;

la valeur du caractre crit promue dans un entier sauf en cas d'erreur ; c Christian Bac 1985-2003

186

16.4. ACCS AU CONTENU DU FICHIER

conditions d'erreur :
int putc(int , FILE *) ;

en cas d'erreur d'criture, la fonction retourne

EOF et positionne les

indicateurs associs (voir 16.8).

synopsis :
dans

cette fonction est identique

fputc() mais elle est ralise par une macro dnie

< stdio.h >.

Les fonctions (macro-expressions) getc() et putc() sont en fait la base de getchar() et putchar que nous avons utilises jusqu'ici.  putchar(c) est dni comme putc(c,stdout) ;  getchar() est dni comme getc(stdin). Comme getchar() la fonction getc() retourne un entier pour pouvoir retourner la valeur EOF en n de chier. Dans le cas gnral, l'entier retourn correspond un octet lu dans le chier et rang dans un entier en considrant l'octet comme tant du type caractre non sign (unsigned

char).

Le programme 16.5 est un exemple d'criture l'cran du contenu d'un chier dont le nom est donn en argument (comportement identique la commande comme tant en mode texte.

cat(1)

du systme UNIX avec

comme argument un seul nom de chier). Le chier est ouvert en mode lecture et il est considr

Programme 16.5

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

#include <stdio.h> int main (int argc, char *argv[]) { FILE *MyFic; int TheCar; if (argc != 2) return 1; MyFic = fopen (argv[1], "r"); if (MyFic == NULL) { printf ("Impossible d ouvrir le fichier %s \n", argv[1]); return 2; } while ((TheCar = fgetc (MyFic)) != EOF) fputc (TheCar, stdout); fclose (MyFic); return 0; }

Lecture caractre par caractre d'un fichier aprs ouverture

Donnes en entre
The quick brown fox jumped over the lazy dog, 1234567890.

Donnes crites sur le fichier standard de sortie

The quick brown fox jumped over the lazy dog, 1234567890.

16.4.2 Accs ligne par ligne


Comme pour les entre-sorties sur les pseudo-chiers standards, il est possible de raliser des oprations de lecture et d'criture ligne par ligne l'intrieur de chiers ouverts. Cet accs ligne par ligne se fait grce aux fonctions : c Christian Bac 1985-2003

CHAPITRE 16.

ENTRES-SORTIES DE LA BIBLIOTHQUE

187

char *fgets(char *, int , FILE *) ;

synopsis :

lit une ligne de caractres ou au plus le nombre de caractres correspondant dans le chier associ au troisime argument. Les dans la mmoire partir de l'adresse donne en le retour chane de

au deuxime argument moins un, caractres de la ligne sont rangs

premier argument. Si le nombre de caractres lu est infrieur la taille, chariot est lu et rang en mmoire. Il est suivi par un caractre nul caractres.

'\0'

de manire

ce que la ligne une fois place en mmoire, puisse tre utilise comme une

arguments :

1. adresse de la zone de stockage des caractres en mmoire, 2. nombre maximum de caractres (taille de la zone de stockage), 3. et la rfrence de type

retour : adresse reue en entre sauf en cas d'erreur ; conditions d'arrt : un ligne est lue (rencontre du conditions d'erreur : synopsis :
sitionne les indicateurs associs (voir 16.8).

FILE

du chier ouvert.

retour chariot), la n de chier est

rencontre, le nombre de caractre lu est gal la taille du buer moins un. la rencontre de la n de chier, la fonction retourne

NULL

et po-

int fputs(const char *, FILE *) ;


cette fonction permet d'crire une chane de caractres rfrence par le premier dans le chier dcrit par le second argument. 1. le premier argument contient l'adresse de la zone mmoire qui contient

argument :

argument

les caractres crire. Cette zone doit tre un chane de caractres (termine par un caractre nul). Elle doit contenir un retour chariot pour obtebir un passage la ligne suivante. 2. le second argument contient la rfrence de type les caractres seront crits.

FILE

du chier ouvert dans lequel

retour : une valeur positive si l'criture s'est correctement droule. conditions d'erreur : en cas d'erreur d'criture, la fonction retourne EOF et positionne les
indicateurs associs (voir 16.8). Pour la lecture ligne ligne, il est ncessaire de donner l'adresse d'un tableau pouvant contenir la ligne. De plus, il faut donner la taille de ce tableau pour que la fonction du tableau. La fonction

fgets()

lit au plus n-1 caractres et elle ajoute un caractre nul ('\0')

fgets() ne dborde pas

aprs le dernier caractre qu'elle a mis dans le tableau. La rencontre du caractre de n de ligne ou de la n de chier provoque la n de la lecture. Le caractre de n de ligne n'est pas mis dans le tableau avant le caractre nul. par un caractre nul ('\0'). Il faut mettre explicitement la n de ligne dans ce tableau pour qu'elle soit prsente dans le chier. Le programme 16.6 ralise la lecture du chier correspondant au nom pass en argument sur la ligne de commande et l'criture de ces lignes sur le chier standard de sortie. Les oprations sont ralises ligne par ligne. Les dirences entre et La fonction

fputs()

crit une ligne dans le chier. Le tableau de caractres doit tre termin

gets()

et

fgets(),

d'une part, et

peuvent s'expliquer par le fait que les fonctions

stdout

puts() et fputs(), d'autre part, puts et gets agissent sur les pseudo-chiers stdin

qui sont le plus souvent des terminaux (cran + clavier).

Les dirences sont les suivantes :  la fonction

gets()

1. ne ncessite pas que lui soit fournie la taille du tableau de lecture. Il faut esprer que les lignes saisies seront plus courtes que la taille du tableau. Comme ces lignes viennent a priori d'un terminal, elles font souvent moins de 80 caractres. c Christian Bac 1985-2003

188

16.4. ACCS AU CONTENU DU FICHIER

Programme 16.6

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

#include <stdio.h> int main (int argc, char *argv[]) { FILE *TheFic; char BigBuf[256];

Lecture ligne ligne d'un fichier aprs ouverture

if (argc != 2) return 1; TheFic = fopen (argv[1], "r"); if (TheFic == NULL) { printf ("Impossible d ouvrir le fichier %s \n", argv[1]); return 2; } while (fgets (BigBuf, sizeof BigBuf, TheFic) != NULL) fputs (BigBuf, stdout); fclose (TheFic); return 0;

Donnes en entre
The quick brown fox jumped over the lazy dog, 1234567890.

Donnes crites sur le fichier standard de sortie

The quick brown fox jumped over the lazy dog, 1234567890.

2. ne met pas le caractre de n de ligne dans le tableau. Ce caractre le caractre de n de chane.  la fonction

est remplac par

puts() : ne ncessite pas la prsence du caractre de n de ligne dans le

tableau.

Ce caractre est ajout automatiquement lors de l'criture.

16.4.3 Accs enregistrement par enregistrement


L'accs par enregistrement permet de lire et d'crire des objets structurs dans un chier. Ces objets structurs sont le plus souvent reprsents en mmoire par des structures. Pour ce type d'accs, le chier doit tre ouvert en mode binaire (voir le programme 16.7 ligne 13). Les donnes changes ne sont pas traites comme des caractres. L'accs par enregistrement se fait grce aux fonctions :

size_t fread(void *Zone, size_t Taille, size_t Nbr, FILE *fp) ; size_t fwrite(void *Zone, size_t Taille, size_t Nbr, FILE *fp) ;
Ces fonctions ont une interface homogne. Elles acceptent une liste identique d'arguments, et retournent le mme type de rsultat. Les arguments sont les suivants : 1. le premier argument, que nous avons appel duquel l'change

Zone,

est l'adresse de l'espace mmoire partir

avec le chier est fait. L'espace mmoire correspondant reoit les enregis-

trements lus, ou fournit les donnes crire dans les enregistrements. Il faut, bien entendu, que l'espace mmoire correspondant l'adresse soit de taille susante pour supporter le transfert des donnes, c'est--dire d'une taille au moins gale c Christian Bac 1985-2003

(Taille * Nbr).

CHAPITRE 16.

ENTRES-SORTIES DE LA BIBLIOTHQUE

189

2. le deuxime argument, que nous avons appel nombre d'octets. 3. le troisime argument, que nous avons appel dsire changer. 4. le dernier argument, que nous avons appel

Taille,

est la taille d'un enregistrement en

Nbr,

est le nombre d'enregistrements que l'on

FILE

fp,

est une rfrence vers une structure de type

correspondant

un chier ouvert dans un mode de transfert binaire.

Ces deux fonctions retournent le nombre d'enregistrements changs. Ces fonctions ont t conues de manire permettre l'change de plusieurs structures, ce qui explique la prsence des deux arguments qui fournissent la taille totale des donnes transfrer. Le programme 16.7 est un exemple, d'utilisation de la fonction la lecture du contenu d'un chier appel un tableau en mmoire

ParcAuto.

fread(). Cet exemple ralise FicParcAuto avec stockage du contenu de ce chier dans

Les cases du tableau sont des structures contenant un entier,

une chane de vingt caractres et trois chanes de dix caractres.

Programme 16.7 Lecture d'enregistrements dans un chier


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

#include <stdio.h> #include <stddef.h> struct automobile { int age; char couleur[20], numero[10], type[10], marque[10]; } ParcAuto[20];

int main (int argc, char *argv[]) { FILE *TheFic; int i; size_t fait; TheFic = fopen ("FicParcAuto", "rb+"); if (TheFic == NULL) { printf ("Impossible d ouvrir le fichier FicParcAuto\n"); return 1; } for (i = 0; i < 20; i++) { fait = fread (&ParcAuto[i], sizeof (struct automobile), 1, TheFic); if (fait != 1) { printf ("Erreur lecture fichier parcauto \n"); return 2; } } fclose (TheFic); return 0; }

Il est possible de demander la lecture des vingt enregistrements en une seule opration, en remplaant les lignes 18 24 par les lignes suivantes :

fait = fread(ParcAuto,sizeof(struct automobile),20,TheFic); if(fait != 20){


c Christian Bac 1985-2003

190

16.5. ENTRE-SORTIES FORMATES

printf ("Erreur lecture fichier parcauto \n"); return 2;

16.5 Entre-sorties formates


Nous avons dj vu comment utiliser

printf()

et

scanf().

Nous allons approfondir nos

connaissances sur ces fonctions et sur les autres fonctions qui font des conversions de format. Les fonctions que nous allons tudier utilisent des formats de conversion entre le modle des donnes machines et le modle ncessaire la vision humaine (chane de caractres). Les lectures formates ncessitent :  le format de description des lectures faire ;  une adresse Les critures formates ncessitent :  le format de description des critures faire ;  les valeurs des variables simples crire. Comme dans le cas de la du premier caractre. lecture, l'criture d'un ensemble de caractres est une opration particulire qui peut se faire partir de l'adresse

4 pour chaque variable simple ou pour un tableau de caractres 5 .

16.5.1 Formats : cas de la lecture


Les formats de conversion servent dcrire les types externes et internes des donnes lire. Les formats peuvent contenir : 1. des caractres "blancs" (espace, tabulation). La prsence d'un caractre et mis la poubelle ; 2. des caractres ordinaires (ni blanc, ni blanc fait que

lorsque des caractres blancs (espace, tabulation, retour chariot) sont lus ils sont consomms

%).

Ces caractres devront tre rencontrs la lecture ;

3. des spcications de conversion, commenant par le caractre Une conversion consiste en : 1. un caractre de pourcentage (%) ;

%.

2. un caractre (optionnel) d'eacement (*) ; dans ce cas la donne lue est mise la poubelle ; 3. un champ (optionnel) dnissant la taille de la donne lire exprime par une valeur entire en base dix ; 4. un caractre (optionnel) de prcision de taille qui peut tre : sur les modes de spcication de la manire suivante : (a) si le format initial est du type qu'entier ordinaire (int) . que la donne est du type entier long (long

l, h ou L. Ces caractres agissent

d ou i ou n, les caractres l et h prcisent respectivement int) ou entier court (short int) plutt

(b) si le format initial est du type

(c)

o ou x ou u, les caractres l et h prcisent respectivement long int) ou entier court non sign (unsigned short int) plutt qu'entier non sign (unsigned int). si le format initial est du type e ou f ou g, les caractres l et L prcisent respectivement que la donne est du type nombre avec point dcimal de grande prcision double) ou nombre avec point dcimal de trs grande prcision (long double) plutt que du type nombre avec point dcimal (float).
que la donne est du type entier long non sign (unsigned

4 Ce 5

qui explique pourquoi il faut un & devant les noms de donnes lire quand ces noms ne sont pas des

tableaux. Des formats particuliers permettent la lecture de plusieurs caractres l'intrieur d'un tableau de caractres.

c Christian Bac 1985-2003

CHAPITRE 16.

ENTRES-SORTIES DE LA BIBLIOTHQUE

191

code % d i o u x e f g c s

conversion ralise lit un % entier sign exprim en base dcimale entier sign exprim en base dcimale entier non sign exprim en base octale entier non sign exprim en base dcimale entier non sign exprim en hexadcimal nombre avec partie dcimale en notation point dcimal ou exponentielle caractre mots ou chane de caractres sans blanc chane de caractres parmi un alphabet adresse, pour faire l'opration inverse de l'criture avec %p permet d'obtenir le nombre d'octets lus dans cet appel

[spcication]
p n

Tab.
5. un code de conversion.

16.1  Code de conversion pour

scanf()

(d) dans tous les autres cas, le comportement est indni.

Les codes de conversion pour La

spcication entre les crochets dnit un alphabet6 de caractres. La donne lue doit tre

scanf()

sont dcrits dans la table 16.1.

conforme cette spcication. La lecture avec un format de spcication retourne une chane de caractres.

16.5.2 Formats : cas de l'criture


Les formats de conversion servent dcrire les types externes et internes des donnes crire. Les formats peuvent contenir : 1. des caractres qui sont recopis dans la chane engendre par l'criture ; 2. et des spcications de conversion. Une spcication de conversion consiste en : 1. un caractre de pourcentage (%) ; 2. des drapeaux (ags) qui modient la signication de la conversion ; 3. la taille minimum du champ dans lequel est insre l'criture de la donne ; (a) la taille est donne en nombre de caractres, (b) pour les chires, si la taille commence par

la donne est cadre gauche.

(c) pour une chane de caractre, si la taille est prcde de 0, la chane est cadre droite et est prcde de zros ; 4. un point suivi de la prcision. La prcision dnit le nombre de chires signicatifs pour de

une donne de type entier, ou le nombre de chires aprs la virgule pour une donne type ottant. Elle indique le nombre de caractres pour une chane ; 5. un

ou un

ou un

signiant court ou long et permettant de prciser :

(a) dans le cas d'une conversion d'un entier (format est un entier court (h) ou long (l) ;

d, i, o, u, x, ou X)

que l'entier crire

6 Cet
un

alphabet est dni soit par la liste des caractres signicatifs, soit par le premier caractre suivi d'un tiret et

le dernier caractre dans l'ordre croissant de la table ASCII. La ngation de l'alphabet peut tre obtenue en mettant

aprs le crochet ouvrant. Pour que le crochet fermant soit dans l'alphabet, il faut qu'il suive immdiatement

le crochet ouvrant.

c Christian Bac 1985-2003

192

16.5. ENTRE-SORTIES FORMATES

code % d i o u x, X e, E f g, G c s p n

conversion ralise crit un % entier sign exprim en base dcimale entier sign exprim en base dcimale entier non sign exprim en base octale entier non sign exprim en base dcimale entier non sign exprim en hexadcimal nombre avec partie dcimale en notation exponentielle nombre avec partie dcimale en notation point dcimal nombre avec partie dcimale, plus petit en taille des formats f ou e caractre chane de caractres la valeur passe est une adresse permet d'obtenir le nombre d'octets crits

Tab.
drapeau + blanc 0 ' #

16.2  Codes de conversion pour

printf()

modication apporte la donne convertie est cadre gauche si la donne est positive le signe + est mis si le rsultat de la conversion ne commence pas par un signe, un blanc est ajout remplissage avec des 0 devant plutot que des blancs pour les conversions dcimales groupement des chires par 3 pour format o augmente la prcision de manire forcer un 0 devant la donne pour format x et X force 0x devant la donne pour format e, E, f, g, et G force le point dcimal pour format g et G les zros aprs le point dcimal sont conservs

Tab.
double).

16.3  Modicateurs de format pour printf

(b) dans le cas d'une conversion d'un nombre avec partie dcimale (format

que le nombre crire est un nombre avec point dcimal de trs grande prcision (long

e, f, g, E, ou G)

6. un code de conversion. Les champs taille et prcision peuvent contenir une un argument

*. Dans ce cas la taille doit tre passe dans [sf]printf. Par exemple les lignes suivantes d'appel printf() sont quivalentes :

printf("Valeur de l'entier Indice : %*d\n",6,Indice); printf("Valeur de l'entier Indice : %6d\n",Indice);


Les codes de conversion sont dcrits dans la table 16.2. La dirence entre

et

vient de la forme d'criture des valeurs dcimales entre 10 et 15.

Dans le premier cas, elles sont crites en minuscule (a-f ), dans le second cas, elles sont crites en majuscule (A-F). De mme, le caractre les formats

et

g.

de la notation exponentielle est mis en minuscule par

Il est mis en majuscule par les formats

et

G.

Selon la norme [ISO89], Le nombre maximum de caractres qui peuvent tre construits dans un appel aux fonctions de type

fprintf()

ne doit pas dpasser

509.

Les drapeaux sont dcrits dans la table 16.3. c Christian Bac 1985-2003

CHAPITRE 16.

ENTRES-SORTIES DE LA BIBLIOTHQUE

193

16.5.3 Conversion sur les entre-sorties standards


Nous avons dj explor dans la section 16.1.3 les deux fonctions d'entre-sorties standards formates qui sont :

int printf(const char *format, ...) ; int scanf(const char *format, ...) ;

16.5.4 Conversion en mmoire


Les deux fonctions de conversion en mmoire s'appellent les suivants :

sprintf

et

sscanf.

Les appels sont

int sprintf(char *string, const char *format, ...) ;

synopsis : conversion de donnes en mmoire par transformation arguments :


1. zone dans laquelle les caractres sont stocks ; 2. format d'criture des donnes ; 3. valeurs des donnes.

en chane de caractres.

retour :

nombre de caractres stocks.

int sscanf(char *string, const char *format, ...) ;

synopsis : lecture formate partir d'une zone mmoire. arguments :


1. zone dans laquelle les caractres sont acquis ; 2. format de lecture des donnes ; 3. adresse des variables aecter partir des donnes.

retour : nombre de variables saisies. conditions d'erreur : la valeur EOF est retourne en cas d'erreur empchant toute lecture.
rsultat dans

sprintf() convertit les arguments arg1, string (chane de caractres).


Inversement,

. . .,

argn

suivant le format de contrle et met le

sscanf

extrait d'une chane de caractres des valeurs qui sont stockes dans des

variables suivant le format de contrle.

16.5.5 Conversion dans les chiers


Deux fonctions fprintf() et fscanf() permettent scanf() sur des chiers ouverts en mode texte : int fprintf(FILE *,const char *, ...) ; de raliser le mme travail que

printf

et

synopsis : criture formate sur un chier ouvert en mode texte. arguments :


1. rfrence vers la structure dcrivant le chier ouvert dans lequel les caractres sont rangs ; 2. format d'criture des donnes ; 3. valeurs des donnes.

retour : nombre de caractres crits. conditions d'erreur : une valeur ngative est retourne en cas d'erreur d'criture.
int fscanf(FILE *,const char *, ...) ;
c Christian Bac 1985-2003

194

16.6.

DPLACEMENT DANS LE FICHIER

synopsis : lecture formate dans un chier ouvert en mode texte. arguments :


1. rfrence vers la structure dcrivant le chier ouvert dans lequel les caractres sont lus ; 2. format de lecture des donnes ; 3. adresse des variables aecter partir des donnes.

retour : nombre de conversions russies. conditions d'erreur : la valeur EOF est


avant la premire conversion). Le programme 16.8 ouvre le chier

retourne en cas d'erreur (n de chier atteinte

/etc/passwd (chier contenant les identications des utili':'.

sateurs) et qui extrait les dirents champs dont les numros d'utilisateur et de groupe, en mettant ces numros dans des variables de type entier. Rappelons qu'une ligne de ce chier contient les champs suivants spars par le caractre deux points  le nom de l'utilisateur,  le mot de passe (crypt) ou un les mots de passe,  le numro d'utilisateur,  le numro de groupe dans lequel l'utilisateur est plac la connexion,  un champ servant mettre des informations complmentaires appel champ champ peut contenir des caractres blancs) ;  le rpertoire de connexion de l'utilisateur,  le chier binaire excutable charger lors de la connexion (le plus souvent un shell). GCOS (ce

si le systme utilise un chier spar (shadow pour stocker

16.6 Dplacement dans le chier


Jusqu' maintenant nous avons vu des fonctions qui modient de manire automatique le pointeur courant dans le chier correspondant (adresse de l'octet dans le chier partir duquel se fait la prochaine opration d'entre-sortie). Nous allons voir les fonctions qui permettent de connaitre la valeur de cette position courante dans le chier et de la modier. Ces fonctions associes la position dans le chier sont :

int fseek(FILE *, long, int) ;

synopsis : change la position courante dans le chier. arguments :


1. rfrence vers la structure dcrivant le chier ouvert ; 2. dplacement l'intrieur du chier en nombre d'octets ; 3. point de dpart du dplacement. Cet argument peut prendre les valeurs suivantes qui selon la norme doivent tre dnies dans le chier dans le chier

< stdio.h > mais sont souvent

< unistd.h >

sur les machines de type "UNIX system V" :

SEEK_SET SEEK_CUR SEEK_END

le dplacement est relatif au dbut du chier ; le dplacement est relatif la position courante ; le dplacement est relatif la n du chier ;

retour : 0 en cas de succs conditions d'erreur : une valeur dirente de zro est retourne si le dplacement ne peut
pas tre ralis.

long ftell(FILE *) ;

synopsis : retourne la valeur de la position courante dans le chier. argument : rfrence vers la structure dcrivant le chier ouvert ;
c Christian Bac 1985-2003

CHAPITRE 16.

ENTRES-SORTIES DE LA BIBLIOTHQUE

195

retour :
1. sur les chiers binaires : nombre d'octets entre la position courante et le dbut du chier. 2. sur les chiers texte : une valeur permettant courant l'endroit actuel.

fseek() de repositionner le pointeur errno


est modie .

int fgetpos(FILE *, fpos_t *) ;

conditions d'erreur :

la valeur

-1L

est retourne, et la variable

synopsis : acquiert la position courante dans le chier. arguments :


1. rfrence vers la structure dcrivant le chier ouvert ; 2. rfrence d'une zone permettant de conserver la position type

retour : 0 en cas de succs conditions d'erreur : une


modie .

fpos_t

courante du chier (le

est souvent un type

quivalent du type entier long) ;

valeur dirente de 0 est retourne, et la variable

errno

est

int fsetpos(FILE *, const fpos_t *) ;

synopsis : change la position courante dans le chier. arguments :


1. rfrence vers la structure dcrivant le chier ouvert ; 2. rfrence d'une zone ayant servi conserver la position courante du chier par un appel prcdent

retour : 0 en cas de succs conditions d'erreur : une void rewind(FILE *) ; synopsis : si la rfrence
modie .

fgetpos() ;

valeur dirente de 0 est retourne, et la variable

errno

est

vers la structure dcrivant le chier ouvert

fonction est quivalente

(void)fseek(fp,0L,0).

fp

est valide cette

Pour illustrer le dplacement l'intrieur d'un chier, nous allons prendre pour exemple la modication de l'ge des voitures dans le chier

FicParcAuto vu prcdemment. Le programme 16.9

ralise la modication d'un enregistrement dans un chier en procdant de la manire suivante : 1. il lit un enregistrement du chier dans une zone en mmoire ; 2. il modie la zone en mmoire ; 3. il replace le pointeur courant du chier sur le dbut de l'enregistrement pour pouvoir rcrire cet enregistrement ; 4. il crit la zone mmoire dans le chier. Cette modication est ralise par le programme 16.9 selon les instructions C suivantes :  la ligne 19 correspond une lecture d'un enregistrement du chier

UneAuto

du type

struct automobile.

dans la zone mmoire

 la ligne 24 modie la valeur du champ

age

dans la structure en mmoire ;

 la ligne 25 modie la position courante du chier pour positionner le pointeur courant l'adress de dbut de l'enregistrement qui est en mmoire.  la ligne 28 crit dans le chier le contenu de la zone mmoire la modication de l'enregistrement sur disque. Ce mme exemple peut aussi tre ralis avec les fonctions

UneAuto. Cette criture provoque fgetpos()


et

fsetpos()

comme

le montre la gure 16.10. La dirence majeure entre ces deux exemples vient du fait que dans la version 16.10 le programme conserve l'information permettant de repositionner le pointeur courant dans le chier, alors que dans le programme 16.9 le programme revient en arrire de la taille d'un enregistrement. Les fonctions

fgetpos()

et

fsetpos()

sont plus appropries pour des

dplacements dans un chier avec des tailles d'enregistrement variables. c Christian Bac 1985-2003

196

16.7.

GESTION DES TAMPONS

16.7 Gestion des tampons


Les entre-sorties sont en gnral buerises

7 (sauf

stderr).

Dans le cas gnral, l'allocation du tampon se fait de manire automatique lors de la premire entre-sortie, la taille de ce tampon est de l'ordre du kilo-octet. Il est cependant possible d'associer un buer avec un chier ouvert par les fonctions dcrites ci-aprs, pour par exemple optimiser la taille de ce tampon par rapport aux critures ralises par le programme. Cette association doit tre faite avant tout change dans le chier ouvert. Le buer se trouve dans l'espace adressable de l'utilisateur. Les appels de fonctions associes la prsence d'un buer sont :

void setbuf(FILE *,char *) ;

synopsis :

associe un buer un chier ouvert, dans le

cas o le pointeur est

NULL,

les

entre-sorties du chier sont non buerises (chaque change donne lieu un appel

arguments :

systme).

1. rfrence vers la structure dcrivant le chier ouvert ; 2. adresse d'une zone mmoire destine devenir le buer d'entre-sortie associ au chier ouvert, cette zone doit avoir une taille prdnie dont la valeur est Elle peut tre gale au pointeur buerises.

NULL,

BUFSIZE.

ce qui rend les entre-sorties du chier non

int setvbuf(FILE * , char * , int , size_t ) ;

synopsis : contrle la gestion de la buerisation d'un chier ouvert avant son utilisation. arguments :
1. rfrence vers la structure dcrivant le chier ouvert ; 2. adresse d'une zone mmoire destine devenir le buer d'entre-sortie associ au chier ouvert, cette zone doit l'adresse est gale avoir la taille donne en quatrime argument. Si

NULL,

la fonction alloue de manire automatique un buer de

la taille correspondante. 3. le type de buerisation, ce paramtre peut prendre les valeurs suivantes dnies

< stdio.h > : _IOFBF signie que les entre-sorties de ce chier seront totalement buerises (par
dans exemple les critures n'auront lieu que lorsque le tampon sera plein).

_IOLBF _IONBF int fflush(FILE *) ;

signie que les entre-sorties seront buerises ligne par ligne (i.e. dans le les entre-sorties sur le chier sont non buerises.

cas de l'criture un retour chariot provoque l'appel systme).

4. la taille de la zone mmoire (buer).

synopsis : vide le buer associ au chier ; argument : rfrence vers la structure dcrivant le chier ouvert
mode mise--jour. Cette rfrence peut tre gale sur l'ensemble des

NULL

en mode criture ou en

auquel cas l'opration porte

retour : 0 dans le cas normal et EOF en cas d'erreur. conditions d'erreur : la fonction retourne EOF si l'criture physique s'est mal passe.
Les entre-sorties sur les terminaux sont buerises ligne par ligne. La fonction permet de forcer l'criture des dernires informations.

chiers ouverts en criture ou en mise--jour ;

fflush()

7 Anglicisme

que l'on peut traduire par tamponnes. Prenons le cas des critures. Elles sont d'abord ralises

dans un espace mmoire local au programme que l'on appelle tampon (buer en anglais). Les caractres sont ensuite transfrs au systme d'exploitatin en bloc. Ceci permet de minimiser les appels au systme d'exploitation (car le tampon de caractres est dans l'espace mmoire du programme) et en gnral d'amliorer les performances. Cette gestion de tampons intermdiaires peut se traduire par une reprsentation non exacte de l'tat du programme par les critures. En eet, les critures sont dires et le tampon d'criture n'est vid que lorsqu'une n de ligne est transmise.

c Christian Bac 1985-2003

CHAPITRE 16.

ENTRES-SORTIES DE LA BIBLIOTHQUE

197

16.8 Gestion des erreurs


Les erreurs des fonctions d'entre-sorties peuvent tre rcupres par le programme. Des variables sont associes aux erreurs sur chaque ux d'entre-sortie. Ces variables ne sont pas directement modiables mais elles sont accessibles travers un ensemble de fonctions qui permettent de les tester ou de les remettre zro. De plus, pour donner plus d'informations sur les causes d'erreur, les fonctions d'entre-sorties utilisent une variable globale de type entier appel

errno.

Cette variable est aussi utilise par les

fonctions de bibliothque servant raliser les appels systme. La valeur de spciant l'chec. Les fonctions associes la gestion des erreurs sont :

errno n'est signicative

que lorsqu'une opration a chou et que l'appel de fonction correspondant a retourn une valeur

int ferror(FILE *) ;

synopsis :

Cette fonction retourne une valeur dirente de zro si la variable qui sert m-

moriser les erreurs sur le chier ouvert correspondant a t aecte lors d'une opration prcdente.

argument : retour :

la rfrence vers la structure dcrivant le chier ouvert pour lequel la recherche

d'erreur est faite. une valeur dirente de zro si une erreur s'est produite.

int feof(FILE *) ;

synopsis :

Cette fonction teste si l'indicateur de n de chier a t positionn sur le chier

ouvert correspondant la rfrence en argument.

argument : retour :

le rfrence vers la structure dcrivant le chier ouvert sur lequel le test de n

de chier est dsir. retourne vrai si la n de chier est atteinte.

void clearerr(FILE *) ;

synopsis :

Cette fonction eace les indicateurs de n de chier et d'erreur du chier ouvert

correspondant la rfrence donne en argument.

argument :

la rfrence vers la structure dcrivant le chier ouvert pour lequel on

dsire

eacer les valeurs de la variable mmorisant les erreurs et de la variable servant mmoriser la rencontre de la n de chier.

void perror(const char *) ;

synopsis : Cette fonction fait la correspondance entre la valeur contenue dans la variable errno et une chane de caractres qui explique de manire succincte l'erreur correspondante.

argument :

Cette fonction accepte un argument du type chane de caractres qui permet

de personnaliser le message. Le programme 16.11 illustre cette gestion d'erreur, par l'ajout des tests d'erreur dans l'exemple de parcours du chier "FicParcAuto" avec modication de l'ge dans les dirents champs.

c Christian Bac 1985-2003

198

16.8. GESTION DES ERREURS

Programme 16.8

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

#include <stdio.h> int main (int argc, char *argv[]) { FILE *pwf; int i, res; char nom[10], passwd[16], gcos[128], rep[255], shell[255]; int uid, gid; pwf = fopen ("passwd", "r"); if (pwf == NULL){ printf ("Impossible d ouvrir le fichier %s \n", "/etc/passwd"); return 1; } while (!feof (pwf)){ res = fscanf (pwf, " %[^:]:", nom); if (res != 1) break; res = fscanf (pwf, "%[^:]:", passwd); if (res != 1) break; res = fscanf (pwf, "%d:", &uid); if (res != 1) break; res = fscanf (pwf, "%d:", &gid); if (res != 1) break; for (i = 0; i < 128; i++){ res = fgetc (pwf); if (res == ':'){ gcos[i] = '\0'; break; } else gcos[i] = res; } res = fscanf (pwf, "%[^:]:", rep); if (res != 1) break; res = fgetc (pwf); if (res != '\n'){ ungetc (res, pwf); res = fscanf (pwf, "%s", shell); if (res != 1) break; } else shell[0] = '\0'; printf ("%s %s %d %d %s %s %s\n", nom, passwd, uid, gid, gcos, rep, shell); } fclose (pwf); return 0;

Lecture avec format dans un fichier texte

Donnes crites sur le fichier standard de sortie


root x 0 0 root /root /bin/bash daemon x 1 1 daemon /usr/sbin /bin/sh bin x 2 2 bin /bin /bin/sh sys x 3 3 sys /dev /bin/sh gdm x 102 101 Gnome Display Manager /var/lib/gdm /bin/false

c Christian Bac 1985-2003

CHAPITRE 16.

ENTRES-SORTIES DE LA BIBLIOTHQUE

199

Programme 16.9 Modications par dplacement dans un chier


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38

#include <stdio.h> #include <stddef.h> struct automobile { int age; char couleur[20], numero[10], type[10], marque[10]; } uneauto;

int main (int argc, char *argv[]) { FILE *fparc; int i; size_t fait; fparc = fopen ("FicParcAuto", "r+b"); if (fparc == NULL){ printf ("Impossible d ouvrir le fichier FicParcAuto \n"); return 1; } for (i = 0; i < 20; i++) { fait = fread (&uneauto, sizeof uneauto, 1, fparc); if (fait != 1) { printf ("Erreur lecture fichier FicParcAuto \n"); return 2; } uneauto.age++; fait = fseek (fparc, (long) -sizeof uneauto, SEEK_CUR); if (fait != 0){ printf ("Erreur deplacement fichier FicParcAuto \n"); return 3; } fait = fwrite (&uneauto, sizeof uneauto, 1, fparc); if (fait != 1) { printf ("Erreur ecriture fichier FicParcAuto fait = %d \n", fait); return 4; } } fclose (fparc); return 0; }

c Christian Bac 1985-2003

200

16.8. GESTION DES ERREURS

Programme 16.10 Dplacements dans un chier avec fgetpos()


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44

#include <stdio.h> #include <stddef.h> struct automobile { int age; char couleur[20], numero[10], type[10], marque[10]; } parc[20];

int main (int argc, char *argv[]) { FILE *fparc; int i; size_t fait; fpos_t curpos; fparc = fopen ("FicParcAuto", "r+b"); if (fparc == NULL){ printf ("Impossible d ouvrir le fichier FicParcAuto \n"); return 1; } for (i = 0; i < 20; i++) { fait = fgetpos (fparc, &curpos); if (fait != 0) { printf ("Erreur acquisition Position \n"); return 2; } fait = fread (&parc[i], sizeof (struct automobile), 1, fparc); if (fait != 1) { printf ("Erreur lecture fichier FicParcAuto \n"); return 3; } parc[i].age++; fait = fsetpos (fparc, &curpos); if (fait != 0) { printf ("Erreur restitution Position \n"); return 4; } fait = fwrite (&parc[i], sizeof (struct automobile), 1, fparc); if (fait != 1) { printf ("Erreur ecriture fichier parcauto fait = %d \n", fait); return 5; } } fclose (fparc); return 0; }

c Christian Bac 1985-2003

CHAPITRE 16.

ENTRES-SORTIES DE LA BIBLIOTHQUE

201

Programme 16.11

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

#include <stdio.h> #include <stddef.h> #include <unistd.h> struct automobile { int age; char couleur[20], numero[10], type[10], marque[10]; } parc;

Gestion des cas d'erreurs pendant la manipulation d'un fichier

int main (int argc, char *argv[]) { FILE *fparc; size_t fait; fparc = fopen ("FicParcAuto", "r+b"); if (fparc == NULL) { perror ("Impossible d ouvrir FicParcAuto"); return 1; } while (1){ fait = fread (&parc, sizeof parc, 1, fparc); if (fait != 1) { if (feof (fparc)) fprintf (stderr, "Fin de fichier FicParcAuto \n"); else fprintf (stderr, "Erreur lecture FicParcAuto\n"); break; } parc.age++; fait = fseek (fparc, (long) -sizeof (parc), SEEK_CUR); if (fait != 0) { perror ("Erreur deplacement FicParcAuto"); break; } fait = fwrite (&parc, sizeof parc, 1, fparc); if (fait != 1) { fprintf (stderr, "Erreur ecriture FicParcAuto fait = %d \n", fait); break; } fflush (fparc); } clearerr (fparc); fclose (fparc); return 0; }

Donnes crites sur le fichier standard d'erreur


Fin de fichier FicParcAuto

c Christian Bac 1985-2003

202

16.8. GESTION DES ERREURS

c Christian Bac 1985-2003

Chapitre 17

Autres fonctions de la bibliothque


17.1 Fonctions de manipulation de chanes de caractres
La bibliothque standard fournit des fonctions de manipulation de chanes de caractres. Il est ncessaire d'inclure le chier tables 17.1 et 17.2.

< string.h >

pour avoir la dnition des fonctions dcrites dans les

17.2 Types de caractres


Il existe des macros expressions dnies dans le test est vrai.          

< ctype.h >

qui permettent de dterminer ou de

changer le type d'un caractre. Ces macros expressions de test retournent un rsultat non nul si

isalpha(c) isupper(c) islower(c) isdigit(c) isspace(c) ispunct(c) isalnum(c) isprint(c) isgraph(c) iscntrl(c)

vrai si c est une lettre (alphabtique). vrai si c est une majuscule (upper case). vrai si c est une minuscule (lower case). vrai si c est un chire. vrai si c est un blanc, interligne ou tab. vrai si c est un caractre de ponctuation. vrai si c est alphabtique ou numrique. vrai si c est achable de 040 0176. vrai si c est graphique de 041 0176. vrai si c est del (0177) ou un caractre de contrle (<040).

Dclaration

Travail

Retour

char *s1, *s2 ; int n ; char *strcat (s1, s2) char *strncat (s1, s2, n) int strcmp (s1, s2) int strncmp (s1, s2, n) char *strcpy (s1, s2) char *strncpy (s1, s2, n) char *s ; int strlen (s)

ajoute la chane s2 derrire s1 ajoute au plus n caractres compare s1 et s2 compare au plus n caractres copie s2 dans s1 copie sur au plus n caractres

pointeur sur s1 pointeur sur s1 nombre positif, nul, ngatif s1>s2 , s1==s2 , s1<s2

taille de s

Tab.

17.1  Fonctions de manipulation simples de chanes de caractres

c Christian Bac 1985-2003

204

17.3.

QUELQUES FONCTIONS GNRALES

Dclaration

Travail

Retour

char *s1, *s2 ; int n ; int c ; char *strchr (s, c) char *strrchr (s, c) char *index(s, c) char *rindex(s, c) char *strpbrk (s1, s2) int strspn (s1, s2) int strcspn (s1, s2)

cherche caractre c dans s idem idem que strchr idem que strrchr cherche 1 caractre de s2 dans s1 1

pointeur sur premire occurrence pointeur sur dernire occurrence

pointeur sur premire occurrence longueur longueur

er

motif dans s1 ne contenant motif dans s1 ne contenant

que des caractres de s2 1

er

aucun caractre de s2

Tab.
   

17.2  Fonctions de manipulation de motifs dans des chanes de caractres

isascii(c) toupper(c) tolower(c) toascii(c)

vrai si c est ASCII (<0200). retourne le caractre majuscule correspondant c. retourne le caractre minuscule correspondant c. masque c avec 0x7f.

Les macros qui transforment un caractre :

17.3 Quelques fonctions gnrales


17.3.1
system()
system(s)
Il est possible de demander au systme l'excution d'un utilitaire. La fonction provoque l'excution de l'utilitaire correspondant la chane de caractre s. Exemple :

system("date") ; calloc()
o et

Nous avons peu parl d'implantation de donnes en mmoire. Il est possible de grer une partie de l'espace dynamiquement par les fonctions  

calloc(n, sizeof (objet))


la zone.

alloue de la place pour

cfree(). n objets

et retourne un pointeur sur

cfree(p)

restitue l'espace point par

a t obtenu par un

calloc().

17.3.2

exit()
exit() comme une rupture de squence. L'instruction return provoque exit() provoque la n du programme. Cette

Bien que n'tant pas une instruction du langage mais un appel une fonction du systme, il est intressant de considrer le fonction la n d'une fonction ; de mme l'appel la fonction

exit() peut tre aussi associe une expression. Cette expression est value et la valeur

obtenue est retourne au processus pre. La valeur 0 signie que le programme s'est bien pass. Prenons le cas du programme 17.1 qui doit lire un chier. Si ce chier est absent, la fonction qui est charge de l'ouvrir peut dcider l'arrt du programme. Nous allons crire cette fonction.

c Christian Bac 1985-2003

CHAPITRE 17.

AUTRES FONCTIONS DE LA BIBLIOTHQUE

205

Programme 17.1 Utilisation de l'appel systme exit()


1 2 3 4 5 6 7 8 9 10 11 12

int ouvre (const char *nom_fichier) { int o; o = open (nom_fichier, 0); if (o == -1) { printf ("impossible d'ouvrir %s\n", nom_fichier); exit (1); } return o; }

c Christian Bac 1985-2003

206

17.3.

QUELQUES FONCTIONS GNRALES

c Christian Bac 1985-2003

GNU Free Documentation License


Version 1.1, March 2000 Copyright c 2000 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.

Preamble
The purpose of this License is to make a manual, textbook, or other written document free in the sense of freedom : to assure everyone the eective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modications made by others. This License is a kind of copyleft, which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software. We have designed this License in order to use it for manuals for free software, because free software needs free documentation : a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals ; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference.

17.4 Applicability and Denitions


This License applies to any manual or other work that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. The Document, below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as you. A Modied Version of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modications and/or translated into another language. A Secondary Section is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (For example, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. c Christian Bac 1985-2003

208

GNU FREE DOCUMENTATION LICENSE

The Invariant Sections are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. The Cover Texts are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Transparent copy of the Document means a machine-readable copy, represented in a format whose specication is available to the general public, whose contents can be viewed and edited directly and straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent le format whose markup has been designed to thwart or discourage subsequent modication by readers is not Transparent. A copy that is not Transparent is called Opaque. Examples of suitable formats for Transparent copies include plain ASCII without markup, AT X input format, SGML or XML using a publicly available DTD, and Texinfo input format, L E standard-conforming simple HTML designed for human modication. Opaque formats include PostScript, PDF, proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML produced by some word processors for output purposes only. The Title Page means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, Title Page means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text.

17.5 Verbatim Copying


You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3. You may also lend copies, under the same conditions stated above, and you may publicly display copies.

17.6 Copying in Quantity


If you publish printed copies of the Document numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts : Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects. If the required texts for either cover are too voluminous to t legibly, you should put the rst ones listed (as many as t reasonably) on the actual cover, and continue the rest onto adjacent pages.

17.7.

MODIFICATIONS

209

If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a publicly-accessible computer-network location containing a complete Transparent copy of the Document, free of added material, which the general network-using public has access to download anonymously at no charge using public-standard network protocols. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public. It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document.

17.7 Modications
You may copy and distribute a Modied Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modied Version under precisely this License, with the Modied Version lling the role of the Document, thus licensing distribution and modication of the Modied Version to whoever possesses a copy of it. In addition, you must do these things in the Modied Version :  Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission.  List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modications in the Modied Version, together with at least ve of the principal authors of the Document (all of its principal authors, if it has less than ve).  State on the Title page the name of the publisher of the Modied Version, as the publisher.  Preserve all the copyright notices of the Document.  Add an appropriate copyright notice for your modications adjacent to the other copyright notices.  Include, immediately after the copyright notices, a license notice giving the public permission to use the Modied Version under the terms of this License, in the form shown in the Addendum below.  Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice.  Include an unaltered copy of this License.  Preserve the section entitled History, and its title, and add to it an item stating at least the title, year, new authors, and publisher of the Modied Version as given on the Title Page. If there is no section entitled History in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modied Version as stated in the previous sentence.  Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the History section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission.  In any section entitled Acknowledgements or Dedications, preserve the section's title, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein.  Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles.

210

GNU FREE DOCUMENTATION LICENSE

 Delete any section entitled Endorsements. Such a section may not be included in the Modied Version.  Do not retitle any existing section as Endorsements or to conict in title with any Invariant Section. If the Modied Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modied Version's license notice. These titles must be distinct from any other section titles. You may add a section entitled Endorsements, provided it contains nothing but endorsements of your Modied Version by various parties  for example, statements of peer review or that the text has been approved by an organization as the authoritative denition of a standard. You may add a passage of up to ve words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modied Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another ; but you may replace the old one, on explicit permission from the previous publisher that added the old one. The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modied Version.

17.8 Combining Documents


You may combine the Document with other documents released under this License, under the terms dened in section 4 above for modied versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodied, and list them all as Invariant Sections of your combined work in its license notice. The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but dierent contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work. In the combination, you must combine any sections entitled History in the various original documents, forming one section entitled History ; likewise combine any sections entitled Acknowledgements, and any sections entitled Dedications. You must delete all sections entitled Endorsements.

17.9 Collections of Documents


You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects. You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document.

17.10.

AGGREGATION WITH INDEPENDENT WORKS

211

17.10 Aggregation With Independent Works


A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, does not as a whole count as a Modied Version of the Document, provided no compilation copyright is claimed for the compilation. Such a compilation is called an aggregate, and this License does not apply to the other self-contained works thus compiled with the Document, on account of their being thus compiled, if they are not themselves derivative works of the Document. If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one quarter of the entire aggregate, the Document's Cover Texts may be placed on covers that surround only the Document within the aggregate. Otherwise they must appear on covers around the whole aggregate.

17.11 Translation
Translation is considered a kind of modication, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License provided that you also include the original English version of this License. In case of a disagreement between the translation and the original English version of this License, the original English version will prevail.

17.12 Termination
You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.

17.13 Future Revisions of This License


The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may dier in detail to address new problems or concerns. See http ://www.gnu.org/copyleft/. Each version of the License is given a distinguishing version number. If the Document species that a particular numbered version of this License "or any later version" applies to it, you have the option of following the terms and conditions either of that specied version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation.

ADDENDUM : How to use this License for your documents


To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page :

212

17.13.

FUTURE REVISIONS OF THIS LICENSE

Copyright c YEAR YOUR NAME. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation ; with the Invariant Sections being LIST THEIR TITLES, with the Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. A copy of the license is included in the section entitled GNU Free Documentation License. If you have no Invariant Sections, write with no Invariant Sections instead of saying which ones are invariant. If you have no Front-Cover Texts, write no Front-Cover Texts instead of Front-Cover Texts being LIST ; likewise for Back-Cover Texts. If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software.

c Christian Bac 1985-2003

Table des programmes exemples


3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 4.1 4.2 4.3 4.4 4.5 4.6 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 Exemple de chier Exemple de chier Exemple de chier

limits.h float.h . stddef.h

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

16 17 17 24 24 24 25 26 28 31 32 33 34 35 38 42 43 50 51 52 53 54 55 58 67 68 69 70 70 71 71 72 72 73 74 75 76 77 78 79 80 81

Suggestion de corrig chapitre 3 exercice 1 . . . . . . . . . . . . . . . . . . . . . . . Suggestion de corrig chapitre 3 exercice 1 second chier . . . . . . . . . . . . . . . Suggestion de corrig chapitre 3 exercice 2 . . . . . . . . . . . . . . . . . . . . . . . Suggestion de corrig chapitre 3 exercice 3 . . . . . . . . . . . . . . . . . . . . . . . Suggestion de corrig chapitre 3 exercice 4 . . . . . . . . . . . . . . . . . . . . . . . Lecture et criture de chane par Lectures multiples avec

scanf()

scanf()

et

printf()

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

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

Suggestion de corrig chapitre 4 exercice 1 . . . . . . . . . . . . . . . . . . . . . . . Suggestion de corrig chapitre 4 exercice 2 . . . . . . . . . . . . . . . . . . . . . . . Suggestion de corrig chapitre 4 exercice 3 . . . . . . . . . . . . . . . . . . . . . . . Suggestion de corrig chapitre 4 exercice 4 . . . . . . . . . . . . . . . . . . . . . . . Dnitions de variables et d'un pointeur . . . . . . . . . . . . . . . . . . . . . . . . Utilisation des oprateurs de masquage . . . . . . . . . . . . . . . . . . . . . . . . . Utilisation des oprateurs de dcalage . . . . . . . . . . . . . . . . . . . . . . . . . Suggestion de corrig chapitre 5 exercice 1 . . . . . . . . . . . . . . . . . . . . . . . Suggestion de corrig chapitre 5 exercice 2 . . . . . . . . . . . . . . . . . . . . . . . Suggestion de corrig chapitre 5 exercice 3 . . . . . . . . . . . . . . . . . . . . . . . Suggestion de corrig chapitre 5 exercice 4 . . . . . . . . . . . . . . . . . . . . . . . Suggestion de corrig chapitre 5 exercice 5 . . . . . . . . . . . . . . . . . . . . . . . Suggestion de corrig chapitre 5 exercice 6 . . . . . . . . . . . . . . . . . . . . . . . Exemple de tests imbriqus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exemple de table de sauts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exemple de table de sauts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exemple de table de sauts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Lecture d'une ligne avec

while

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

Recopie d'une chane avec une boucle

while for

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

Lecture d'une ligne avec for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dcomposition des puissances de dix d'un nombre avec un Utilisation du continue dans une boucle

do while

. . . . . . . .

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

6.10 Utilisation des ruptures de squence dans une boucle 6.11 Lecture d'une ligne avec 6.12 Utilisation de 6.13 Utilisation de

for et break l'infme goto . . . . . . plusieurs return . . . .

for

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

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

6.14 Suggestion de corrig chapitre 6 exercice 1 . . . . . . . . . . . . . . . . . . . . . . . 6.15 Suggestion de corrig chapitre 6 exercice 2 . . . . . . . . . . . . . . . . . . . . . . . 6.16 Suggestion de corrig chapitre 6 exercice 3 . . . . . . . . . . . . . . . . . . . . . . . 6.17 Suggestion de corrig chapitre 6 exercice 4 . . . . . . . . . . . . . . . . . . . . . . . 6.18 Suggestion de corrig chapitre 6 exercice 5 . . . . . . . . . . . . . . . . . . . . . . . 6.19 Suggestion de corrig chapitre 6 exercice 6 . . . . . . . . . . . . . . . . . . . . . . . c Christian Bac 1985-2003

214

TABLE DES PROGRAMMES EXEMPLES

7.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8 7.9 8.1 8.2 8.3 8.4 8.5 9.1 9.2 9.3 9.4 9.5 9.6 9.7 9.8 9.9

Ensemble de tests non structur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ensemble de tests structur non mis en page Ensemble de tests structur et mis en page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

87 88 89 90 91 92 93 93 93 105 107 108 109 110 115 117 117 122 123 124 125 126 127 130 137 138 138 139 140 141 144 145 145 146 147 148 149 150 151 152 154 160 162 163 163 164 166 167 169 173 174 175 175 176

Ensemble de tests structur et mis en page avec commentaires . . . . . . . . . . . . Ensemble de tests structur, mis en page et tiquet Ensemble de tests par table de branchement . . . . . . . . . . . . . . . . . . . . . . Boucle ralise par des tests et sauts . . . . . . . . . . . . . . . . . . . . . . . . . . Boucle ralise par un for() Achage des arguments de Arguments de . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Boucle ralise par un for() et mise en page . . . . . . . . . . . . . . . . . . . . . .

main()

main()

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

caractres un--un

Suggestion de corrig chapitre 8 exercice 1 . . . . . . . . . . . . . . . . . . . . . . . Suggestion de corrig chapitre 8 exercice 2 . . . . . . . . . . . . . . . . . . . . . . . Suggestion de corrig chapitre 8 exercice 3 . . . . . . . . . . . . . . . . . . . . . . . Exemples de prototypes de fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . Dclarations candidates multiple d'une variable . . . . . . . . . . . . . . . . . . . . Dclaration explicite et dclaration candidate d'une variable . . . . . . . . . . . . . Suggestion de corrig chapitre 9 exercice 1 fonctions Suggestion de corrig chapitre 9 exercice 1 Suggestion de corrig chapitre 9 exercice 2 Suggestion de corrig chapitre 9 exercice 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

main() main() main()

Suggestion de corrig chapitre 9 exercice 2 fonctions

Suggestion de corrig chapitre 9 exercice 3 chier d'inclusion

10.1 Dnition de tableaux et initialisations . . . . . . . . . . . . . . . . . . . . . . . . . 10.2 Accs un tableau deux dimensions avec un pointeur 10.3 Algorithme d'un tri simple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.4 Suggestion de corrig chapitre 10 exercice 1 chier d'inclusion . . . . . . . . . . . . 10.5 Suggestion de corrig chapitre 10 exercice 1 fonctions . . . . . . . . . . . . . . . . . 10.6 Suggestion de corrig chapitre 10 exercice 1 11.1 Dnition de structures 11.2 Dnition de structures

main

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

10.7 Suggestion de corrig chapitre 10 exercice 1 fonction de tri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

11.3 Structures et listes chanes 11.4 Structures et champs de bits

11.5 Suggestion de corrig chapitre 11 exercice 1 11.6 Suggestion de corrig chapitre 11 exercice 2

12.1 Utilisation d'une union . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.2 Utilisation d'une union . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.3 Suggestion de corrig chapitre 12 exercice 1 12.4 Suggestion de corrig chapitre 12 exercice 2 14.1 Suggestion de corrig chapitre 14 exercice 1 14.2 Suggestion de corrig chapitre 14 exercice 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13.1 Utilisation d'numrations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14.3 Suggestion de corrig chapitre 14 exercice 3 chier d'inclusion . . . . . . . . . . . . 14.4 Suggestion de corrig chapitre 14 exercice 3 fonctions . . . . . . . . . . . . . . . . . 14.5 Suggestion de corrig chapitre 14 exercice 3 15.1 Traitement des commentaires 15.2 Erreur due au traitement des commentaires 15.4 Evaluation de macros par CPP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15.3 Interprtation des variables par le prprocesseur

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

15.5 Exemple d'utilisation du #if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15.6 Exemples de slection de code par 15.7 Slection de code par

#ifdef

#ifdef

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

imbriqus

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

15.8 Suggestion de corrig chapitre 15 exercice 1 dnition des macros . . . . . . . . . . c Christian Bac 1985-2003

TABLE DES PROGRAMMES EXEMPLES

215

15.9 Suggestion de corrig chapitre 15 exercice 1 15.10Suggestion de corrig chapitre 15 exercice 2

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

177 178 181 182 184 185 186 188 189 198 199 200 201 205

16.1 Lecture et criture caractre par caractre sur les chiers standards . . . . . . . . . 16.2 Lecture ligne par ligne sur les chiers standards . . . . . . . . . . . . . . . . . . . . 16.3 Ouverture d'un chier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.4 Ouverture et fermeture d'un chier . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.5 Lecture caractre par caractre d'un chier aprs ouverture 16.6 Lecture ligne ligne d'un chier aprs ouverture 16.7 Lecture d'enregistrements dans un chier 16.8 Lecture avec format dans un chier texte . . . . . . . . . . . . . . . . . . .

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

16.9 Modications par dplacement dans un chier . . . . . . . . . . . . . . . . . . . . . 16.10Dplacements dans un chier avec fgetpos() . . . . . . . . . . . . . . . . . . . . . . 16.11Gestion des cas d'erreurs pendant la manipulation d'un chier . . . . . . . . . . . . 17.1 Utilisation de l'appel systme

exit() .

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

c Christian Bac 1985-2003

216

TABLE DES PROGRAMMES EXEMPLES

c Christian Bac 1985-2003

Table des gures


1.1 1.2 1.3 1.4 Structure d'un programme C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 4 5 6 Fichier source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Structure d'une fonction C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Schma de fonctionnement de

cc

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

3.1

Chane de caractres constante

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

15

4.1

Programme qui crit Bonjour . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

27

5.1 5.2

Exemple de relation entre pointeur et variable . . . . . . . . . . . . . . . . . . . . . Mise en relation d'un pointeur et d'une variable . . . . . . . . . . . . . . . . . . . .

38 38

6.1 6.2 6.3 6.4 6.5 6.6

Organigramme du Organigramme du Organigramme du

while for

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

60 61 62 64 64 65

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

do while .
dans un dans un dans un

break break break

et et et

continue continue continue

for

while

do while

8.1 8.2 8.3 8.4 8.5

Structure d'une fonction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pile et passage de constantes Pile et passage de variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

95 98 100 101 104

Pile et passage de variables avec rfrence . . . . . . . . . . . . . . . . . . . . . . . Arguments de

main()

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

9.1 9.2 9.3 9.4 9.5 9.6 9.7 9.8

Du source l'excutable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Survol d'un chier source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

112 112 113 115 116 116 118 119

Exemple de visibilit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Visibilit des variables entre modules . . . . . . . . . . . . . . . . . . . . . . . . . . Visibilit des fonctions entre modules . . . . . . . . . . . . . . . . . . . . . . . . . . Visibilit des fonctions dans un module . . . . . . . . . . . . . . . . . . . . . . . .

Utilisation de chier d'inclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Rduction de visibilit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . c Christian Bac 1985-2003

218

TABLE DES FIGURES

9.9

Variables locales statiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

120

10.1 Tableau de dix entiers

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

129 130 131 131 134 134 135

10.2 Tableau de dix entiers initialis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.3 Adresses dans un tableau de dix entiers 10.4 Tableau deux dimensions . . . . . . . . . . . . . . . . . . . . . . . .

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

10.5 Pointeur et tableau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.6 Tableau de pointeurs sur des variables dans un tableau . . . . . . . . . . . . . . . . 10.7 Accs un tableau deux dimensions avec un pointeur . . . . . . . . . . . . . . .

c Christian Bac 1985-2003

Liste des tableaux


3.1 3.2 3.3 3.4 Longueur des types de base sur quelques machines . . . . . . . . . . . . . . . . . . 13 18 21 22 Variables et classes mmoire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exemples d'initialisations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Exemples de conversion implicite . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4.1 4.2

Conversions usuelles de Exemples de

printf scanf

et

scanf

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

29 30

printf

et

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

5.1 5.2 5.3 5.4 5.5 5.6

Liste des oprateurs unaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Liste des oprateurs binaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Liste des oprateurs binaires d'aectation . . . . . . . . . . . . . . . . . . . . . . .

37 41 44 45 45 46

Exemples d'oprateurs binaires d'aectation . . . . . . . . . . . . . . . . . . . . . . Oprateur ternaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Prcdence des oprateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

6.1 6.2

Syntaxe du

while

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . et du

60 61

Comparaison du

for

while

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

7.1

C et Structures Fondamentales

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

85

8.1 8.2 8.3 8.4

Exemples de dnition de fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . Exemples d'appels de fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

96 97 99 102

Pointeurs et appels de fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Conversions de type un-aire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

9.1

Rgle fondamentale de visibilit . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

113

10.1 Addition d'un entier un pointeur 10.2 Soustraction de deux pointeurs

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

132 133

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

11.1 Accs aux champs d'une structure

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

144

14.1 Exemples d'objets complexes

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

159

c Christian Bac 1985-2003

220

LISTE DES TABLEAUX

15.1 Utilisation d'une constante de compilation . . . . . . . . . . . . . . . . . . . . . . .

168

16.1 Code de conversion pour

scanf() . printf()

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

191 192 192

16.2 Codes de conversion pour

16.3 Modicateurs de format pour printf

17.1 Fonctions de manipulation simples de chanes de caractres

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

203 204

17.2 Fonctions de manipulation de motifs dans des chanes de caractres . . . . . . . . .

c Christian Bac 1985-2003

Bibliographie
[BK78] D.M. Ritchie B.W. Kernighan.

The C Programming Language.

Prentice Hall Inc., En-

glewood Clis, New Jersey, Mars 1978. [BK88] D.M. Ritchie B.W. Kernighan.

The C Programming Language Second Edition. Bell System Technical Journal,

Prentice

Hall Inc., Englewood Clis, New Jersey, 1988. [Bou78] S. Bourne. The UNIX Shell. 57(6) :19711990,

July/August 1978. [Dax92] P. Dax. 1992. [Dij65] E.W. Dijkstra. Programming Considered as a Human Activity. In pages 213217, 1965. [Dij68] E.W. Dijkstra. GO TO Statements Considered Harmful. 11(3) :147148, Mars 1968. [DR78]

Langage C 7eme Edition.

Eyrolles, 61, Boulevard Saint-Germain, 75005 Paris,

Proc. IFIP Congress,

Communications of the ACM,

Bell System Technical Journal,

S.C. Johnson D.M. Ritchie. Portabilty of C Programs and the UNIX Operating System. 57(6) :20212048, July/August 1978. ISO/IEC, 1989. ISO/IEC, 1999.

[ISO89] ISO/IEC, editor. [ISO99] ISO/IEC, editor. [SJ78]

Programming Language C. Programming Language C.

M.E. Lesk S.C. Johnson. Language Development Tools. 57(6) :21552176, July/August 1978.

Bell System Technical Journal,

[Str86]

B. Stroustrup.

The C++ Programming Language.

Prentice Hall Inc., Englewood Clis,

New Jersey, 1986. [Wir71] N. Wirth. Program Development by Stepwise Renement. 14(4) :221227, Avril 1971. [Wir74] N. Wirth. On the Composition of Well Structured Programs. 6(4) :247259, Decembre 1974.

Communications of the ACM, ACM Computing Survey,

c Christian Bac 1985-2003

222

INDEX

Index
#dene, 165, 168, 170 #else, 165, 170 #endif, 165, 170 #if, 165, 170, 171 #ifdef, 165, 170, 171 #ifndef, 165, 170, 171 #include, 165, 166, 179 #undef, 165, 169 accolade, 5, 10, 21, 28, 47, 85, 96, 129 adresse, 11, 15, 19, 20, 23, 24, 29, 38, 39, 48, 97, 99, 103, 105, 106, 113, 120, 129 133, 135, 136, 144, 145, 150, 151, 157, 158, 160, 181, 182, 187, 188, 190, 193, 194, 196 aectation, 3, 15, 17, 19, 20, 29, 37, 43, 44, 47, 49, 57, 62, 99, 114, 132, 144 alias, 7, 165 appel, 13, 5, 11, 17, 19, 22, 23, 28, 29, 39, 40, 42, 43, 46, 63, 65, 9597, 99, 102, 103, 105, 106, 113115, 117, 119 121, 157, 158, 160, 161, 166, 168 170, 180182, 184, 185, 188, 189, 192 197, 204 argument, 11, 23, 27, 28, 65, 97, 99, 102, 103, 105, 111, 114117, 121, 133, 136, 144, 145, 168, 180189, 192197 associativit, 46, 47, 158 bibliothque, 3, 7, 27, 28, 63, 96, 179, 183, 197, 203 binaire, 2, 5, 4042, 44, 46, 47, 103, 114, 145, 170, 183, 184, 188, 189, 194, 195 bit, 2, 3, 1113, 15, 20, 22, 4044, 47, 49, 102, 145, 146, 151, 180 bloc, 5, 17, 47, 62, 63, 65, 95, 96, 114, 119, 120, 196 boolen, 57, 168 boucle, 5, 6064, 66, 8486, 121, 161 caractre, 13, 7, 911, 1315, 1925, 2729, 31, 32, 44, 59, 60, 6266, 86, 102, 103, 132, 150, 151, 165, 168, 179 183, 185194, 196, 197, 203, 204 case, 46, 59, 99, 133 crire, 1, 3, 12, 15, 23, 24, 27, 29, 31, 32, 37, 43, 44, 48, 49, 62, 66, 8385, 96, 102, c Christian Bac 1985-2003 champs de bit, 22, 102, 145, 146 char, 1, 103, 132, 182, 183, 187, 193, 196, 197 chargeable, 7 classe, 10, 11, 17, 106, 113, 114 commentaire, 7, 85, 111, 165, 182 compilateur, 13, 5, 79, 1113, 15, 16, 18 21, 27, 28, 40, 41, 46, 60, 65, 84, 105, 106, 111, 113, 114, 116, 117, 130, 132, 133, 136, 144, 149, 150, 155, 157, 165168, 170, 171 compilation, 2, 5, 8, 9, 18, 25, 28, 84, 95, 111, 113, 114, 117, 118, 120, 165, 166, 168171 constante, 911, 1315, 17, 22, 37, 40, 59, 99, 102, 103, 129, 130, 133, 153155, 168, 170, 171, 179 continue, 10, 59, 62, 86, 106 contrle, 1, 5, 7, 27, 43, 47, 57, 6062, 114, 116, 120, 193, 196, 203 conversion, 21, 22, 29, 99, 102, 132, 150, 190 194 corps, 5, 23, 65, 95, 96, 111, 116, 168 chane, 2, 3, 7, 10, 14, 15, 21, 23, 28, 29, 31, 32, 60, 65, 66, 86, 103, 117, 165, 168, 179, 181183, 187191, 193, 197, 203, 204 champ, 9, 22, 102, 143146, 149151, 190 192, 194, 195, 197

dclaration, 3, 18, 23, 29, 95, 96, 111, 114 119, 129, 132, 135, 157, 158, 160 default, 10 dnition, 3, 5, 7, 11, 12, 1521, 23, 28, 38, 40, 43, 47, 83, 95, 96, 106, 111, 114, 116119, 129, 131133, 143146, 149, 153, 157, 158, 161, 165, 168171, 179, 203 double, 10, 43, 65, 121 dure de vie, 17, 18, 120

INDEX

223

115, 130, 155, 158, 161, 180, 182, 185, 187, 188, 190192, 195, 204 criture, 2, 28, 29, 31, 42, 59, 66, 135, 136, 179188, 190193, 195, 196 dition de lien, 3, 7, 8, 23, 103, 114 else, 10, 57 enchaneur de passe, 169, 170 entier, 1, 1113, 15, 19, 20, 2225, 29, 31, 3844, 48, 49, 62, 63, 66, 85, 97, 99, 102, 103, 106, 114, 129132, 135, 146, 149151, 153155, 157, 160, 161, 171, 180, 185, 186, 189191, 194, 195, 197 entry, 10 numration, 22, 102, 153155 tiquette, 9, 10, 65, 85 excutable, 2, 5, 8, 42, 103, 114, 170, 194 excution, 5, 11, 15, 1719, 39, 40, 59, 6163, 65, 97, 99, 102, 105, 119, 120, 132, 170, 183, 204 expression, 5, 7, 10, 11, 2123, 3747, 49, 57, 5962, 65, 96, 102, 106, 130, 133, 154, 155, 157, 165, 168, 169, 171, 179, 180, 203, 204 extern, 10 externe, 3, 23, 111, 190, 191

instruction, 2, 5, 7, 10, 20, 23, 28, 29, 38, 39, 42, 43, 47, 49, 5766, 83, 84, 95, 96, 103, 106, 111, 168, 170, 195, 204 int, 10, 41, 63, 116, 117, 132, 186, 196 interface, 5, 27, 28, 95, 96, 102, 113, 115, 119, 188 langage, 13, 5, 812, 16, 23, 27, 29, 37, 40, 41, 44, 46, 47, 57, 59, 8385, 95, 97, 102, 103, 111, 115117, 119, 129, 130, 143145, 153, 154, 160, 171, 179, 182, 185, 204 lecture, 7, 15, 28, 29, 31, 32, 42, 46, 62, 63, 66, 83, 85, 121, 135, 158, 165, 179187, 189191, 193195 lire, 2729, 32, 44, 66, 121, 135, 150, 171, 180, 181, 188, 190, 204 local, 18, 23, 114, 132, 196 long, 10, 15, 22, 25, 40, 114, 190, 191 main, 5, 23, 28, 31, 65, 102, 103, 106, 121, 133, 136, 161 mmoire, 1, 11, 12, 15, 1720, 28, 38, 42, 95, 97, 99, 102, 111, 114, 120, 129132, 143, 149, 150, 157, 179, 181, 187 189, 193, 195, 196, 204 norme, 13, 8, 9, 11, 12, 15, 21, 22, 40, 102, 115, 146, 153, 170, 180, 192, 194 objet, 2, 8, 1820, 28, 29, 99, 111, 114, 118, 130132, 143, 146, 158, 160, 183, 188, 204 octet, 13, 11, 12, 14, 15, 38, 40, 60, 130, 145, 179, 180, 186, 189, 194196 oprateur, 12, 16, 20, 29, 32, 3748, 57, 62, 66, 131, 158 optimiseur, 5, 7 paramtre, 5, 95, 97, 99, 102, 103, 105, 106, 113, 196 pile, 17, 97, 99, 102, 103, 105, 106, 132 pointeur, 1, 11, 1820, 23, 24, 38, 39, 48, 97, 99, 103, 105, 106, 120, 121, 129, 131133, 135, 136, 145147, 158, 160, 161, 181, 183185, 194196, 204 prcdence, 45, 46, 158 prprocesseur, 168171, 180 printf, 28, 29, 31, 66, 103, 115, 182, 190, 192, 193 procdure, 95 programmation, 2, 3, 5, 63, 66, 83, 84, 117, 179, 182 prototype, 3, 114118, 158, 179, 184

faux, 40, 57, 132 chier, 2, 3, 5, 7, 8, 11, 15, 16, 18, 23, 27, 28, 31, 4043, 60, 62, 64, 96, 103, 111, 113, 114, 116119, 121, 136, 154, 165 171, 179189, 193197, 203, 204 oat, 10, 114 ottant, 2325, 31, 32, 161, 171, 191 fonction, 3, 5, 7, 911, 1618, 22, 23, 27 29, 31, 46, 57, 60, 63, 65, 86, 9597, 99, 102, 103, 105, 106, 111, 113121, 132, 133, 135, 136, 144, 145, 158, 160, 161, 165, 168, 171, 172, 179 190, 192197, 203, 204 for, 3, 10, 61 format, 7, 9, 28, 29, 31, 103, 180, 182, 183, 185, 190194 fortran, 10

global, 17, 20, 23, 114, 120 goto, 10

if, 10, 19, 57, 158 initialisation, 10, 11, 17, 20, 21, 61, 62, 117, 120, 129, 130, 132

c Christian Bac 1985-2003

224

INDEX

qualicatif, 11, 12, 15, 18 rfrence, 2, 3, 7, 18, 23, 40, 114, 116, 168, 184, 185, 187, 189, 193197 register, 10 relogeable, 7 retour, 11, 14, 31, 45, 6366, 9597, 99, 105, 106, 145, 171, 180185, 187, 190, 193 197 return, 10, 65, 96, 102, 204 rupture, 5, 10, 62, 63, 66, 204 scanf, 28, 29, 31, 99, 115, 182, 190, 191, 193 short, 10, 41, 190 sizeof, 10, 12, 40, 132, 204 source, 2, 3, 5, 7, 18, 43, 46, 85, 95, 96, 111, 113, 117, 118, 136, 165, 168, 170 static, 120 statique, 18, 23, 102, 119, 120 struct, 10, 19 structure, 13, 9, 1921, 47, 8385, 103, 111, 118, 120, 135, 143147, 149, 150, 158, 160, 161, 179, 184, 188, 189, 193 197 structur, 83, 84, 121, 144, 188 systme, 1, 2, 5, 7, 8, 15, 27, 28, 41, 42, 60, 84, 85, 102, 103, 121, 154, 166, 170, 171, 179, 180, 183, 184, 186, 194, 196, 197, 204 table de branchement, 58, 85 tableau, 12, 15, 1825, 28, 29, 37, 41, 44, 46, 48, 6064, 66, 84, 86, 96, 97, 99, 102, 103, 120, 129133, 135, 136, 144, 145, 147, 157, 158, 160, 161, 165, 168, 179, 181, 183, 187190 ternaire, 45, 47, 66 test, 5, 4245, 47, 57, 5962, 65, 84, 85, 130, 154, 168, 171, 197, 203 type, 13, 5, 7, 923, 2729, 31, 3844, 47, 57, 60, 62, 63, 65, 66, 84, 85, 9597, 99, 102, 103, 105, 106, 111, 113120, 130133, 135, 143146, 149, 150, 153 155, 157, 158, 160, 161, 166, 168, 170, 171, 179, 180, 182192, 194 197, 203 typedef, 10 types prdnis, 11, 16 unaire, 12 union, 149, 150, 161 UNIX, 1, 2, 5, 7, 8, 27, 28, 41, 42, 60, 85, 103, 132, 154, 166, 180, 186, 194

unsigned, 10 valeur, 2, 1114, 16, 17, 1923, 25, 28, 3845, 4749, 57, 5963, 65, 66, 85, 96, 97, 99, 102, 105, 106, 113, 120, 129132, 150, 153155, 168171, 180182, 185 187, 190, 192197, 204 variable, 3, 5, 7, 912, 1520, 22, 23, 2729, 31, 32, 3745, 47, 49, 57, 59, 62, 65, 9597, 99, 102, 103, 105, 106, 111, 113115, 117120, 130133, 135, 143 146, 149, 150, 153155, 157, 158, 165, 167171, 182, 190, 193195, 197 visibilit, 3, 11, 17, 18, 113, 115, 120 void, 10 vrai, 40, 57, 197, 203 while, 62

c Christian Bac 1985-2003

Vous aimerez peut-être aussi