Le Langage C

Embed Size (px)

Citation preview

  • 5/21/2018 Le Langage C

    1/125

    Universite de la Mediterranee

    Faculte des Sciences de Luminy

    Le langage CLicences Maths & Informatique Master Mathematiques Master C.C.I.

    Henri GarretaDepartement dInformatique - LIF

  • 5/21/2018 Le Langage C

    2/125

    TABLE DES MATIERES TABLE DES MATI ERES

    Table des matieres

    1 Elements de base 51.1 Structure generale dun programme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51.2 Considerations lexicales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

    1.2.1 Presentation du texte du programme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51.2.2 Mots-cles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

    1.2.3 Identificateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61.2.4 Operateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

    1.3 Constantes litterales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71.3.1 Nombres entiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71.3.2 Nombres flottants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71.3.3 Caracteres et chanes de caracteres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71.3.4 Expressions constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

    1.4 Types fondamentaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91.4.1 Nombres entiers et caracteres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91.4.2 Types enumeres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111.4.3 Nombres flottants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

    1.5 Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

    1.5.1 Syntaxe des declarations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111.5.2 Visibilite des variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121.5.3 Allocation et duree de vie des variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131.5.4 Initialisation des variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131.5.5 Variables locales statiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141.5.6 Variables critiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141.5.7 Variables constantes et volatiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

    1.6 Variables, fonctions et compilation separee . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151.6.1 Identificateurs publics et prives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151.6.2 Declaration dobjets externes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

    2 Operateurs et expressions 18

    2.1 Generalites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182.1.1 Lvalue et rvalue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182.1.2 Priorite des operateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

    2.2 Presentation detaillee des operateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192.2.1 Appel de fonction() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192.2.2 Indexation [] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202.2.3 Selection. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212.2.4 Selection dans un objet pointe -> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212.2.5 Negation !. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222.2.6 Complement a 1 ~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222.2.7 Les celebres ++ et -- . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222.2.8 Moins unaire- . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232.2.9 Indirection* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232.2.10 Obtention de ladresse & . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242.2.11 Operateur sizeof . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242.2.12 Conversion de type (cast operator) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252.2.13 Operateurs arithmetiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272.2.14 Decalages > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282.2.15 Comparaisons == != < >= . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282.2.16 Operateurs de bits &| ^. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292.2.17 Connecteurs logiques&& et || . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302.2.18 Expression conditionnelle ? :. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312.2.19 Affectation= . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312.2.20 Autres operateurs daffectation += *= etc. . . . . . . . . . . . . . . . . . . . . . . . . . . 322.2.21 Loperateur virgule , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

    2.3 Autres remarques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342.3.1 Les conversions usuelles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342.3.2 Lordre devaluation des expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342.3.3 Les operations non abstraites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

    2 c H. Garreta, 1988-2006

  • 5/21/2018 Le Langage C

    3/125

    TABLE DES MATIERES TABLE DES MATI ERES

    3 Instructions 363.1 Syntaxe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363.2 Presentation detaillee des instructions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

    3.2.1 Blocs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373.2.2 Instruction-expression . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373.2.3 Etiquettes et instruction goto. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383.2.4 Instructionif...else... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

    3.2.5 Instructionswhile et do...while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393.2.6 Instructionfor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403.2.7 Instructionswitch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 413.2.8 Instructionsbreak et continue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423.2.9 Instructionreturn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

    4 Fonctions 444.1 Syntaxe ANSI ou avec prototype . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

    4.1.1 Definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 444.1.2 Type de la fonction et des arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 444.1.3 Appel des fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 454.1.4 Declaration externe dune fonction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

    4.2 Syntaxe originale ou sans prototype . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 464.2.1 Declaration et definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 464.2.2 Appel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 474.2.3 Coexistence des deux syntaxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

    4.3 Arguments des fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 484.3.1 Passage des arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 484.3.2 Arguments de type tableau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 484.3.3 Arguments par adresse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 494.3.4 Arguments en nombre variable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50

    5 Objets structures 525.1 Tableaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52

    5.1.1 Cas general . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52

    5.1.2 Initialisation des tableaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 525.1.3 Chanes de caracteres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

    5.2 Structures et unions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 545.2.1 Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 545.2.2 Unions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 565.2.3 Champs de bits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

    5.3 Enumerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 575.4 Declarateurs complexes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

    5.4.1 Cas des declarations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 585.4.2 Pointeurs et tableaux constants et volatils . . . . . . . . . . . . . . . . . . . . . . . . . . . 605.4.3 La declarationtypedef . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 615.4.4 Cas des types desincarnes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62

    6 Pointeurs 646.1 Generalites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64

    6.1.1 Declaration et initialisation des pointeurs . . . . . . . . . . . . . . . . . . . . . . . . . . . 646.1.2 Les pointeurs generiques et le pointeur NULL. . . . . . . . . . . . . . . . . . . . . . . . . . 65

    6.2 Les pointeurs et les tableaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 666.2.1 Arithmetique des adresses, indirection et indexation . . . . . . . . . . . . . . . . . . . . . 666.2.2 Tableaux dynamiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 686.2.3 Tableaux multidimensionnels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 696.2.4 Tableaux multidimensionnels dynamiques . . . . . . . . . . . . . . . . . . . . . . . . . . . 706.2.5 Tableaux de chanes de caracteres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 726.2.6 Tableaux multidimensionnels formels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74

    6.2.7 Tableaux non necessairement indexes a partir de zero . . . . . . . . . . . . . . . . . . . . 746.2.8 Matrices non dynamiques de taille inconnue . . . . . . . . . . . . . . . . . . . . . . . . . . 766.3 Les adresses des fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

    6.3.1 Les fonctions et leurs adresses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 776.3.2 Fonctions formelles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78

    c H. Garreta, 1988-2006 3

  • 5/21/2018 Le Langage C

    4/125

    TABLE DES MATIERES TABLE DES MATI ERES

    6.3.3 Tableaux de fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 796.3.4 Flou artistique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80

    6.4 Structures recursives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 816.4.1 Declaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 816.4.2 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 816.4.3 Structures mutuellement recursives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

    7 Entrees-sorties 857.1 Flots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85

    7.1.1 Fonctions generales sur les flots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 867.1.2 Les unites standard dentree-sortie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88

    7.2 Lecture et ecriture textuelles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 887.2.1 Lecture et ecriture de caracteres et de chanes . . . . . . . . . . . . . . . . . . . . . . . . . 887.2.2 Ecriture avec formatprintf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 907.2.3 Lecture avec formatscanf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 937.2.4 A propos de la fonction scanf et des lectures interactives . . . . . . . . . . . . . . . . . . 957.2.5 Les variantes deprintf et scanf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97

    7.3 Operations en mode binaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 977.3.1 Lecture-ecriture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 977.3.2 Positionnement dans les fichiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98

    7.4 Exemples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 997.4.1 Fichiers en vrac . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 997.4.2 Fichiers binaires et fichiers de texte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1007.4.3 Fichiers en acces relatif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101

    7.5 Les fichiers de bas niveau dUNIX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102

    8 Autres elements du langage C 1048.1 Le preprocesseur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104

    8.1.1 Inclusion de fichiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1048.1.2 Definition et appel des macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1058.1.3 Compilation conditionnelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106

    8.2 La modularite de C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108

    8.2.1 Fichiers en-tete . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1098.2.2 Exemple : stdio.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110

    8.3 Deux ou trois choses bien pratiques... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1128.3.1 Les arguments du programme principal . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1128.3.2 Branchements hors fonction : setjmp.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1148.3.3 Interruptions : signal.h. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115

    8.4 La bibliotheque standard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1168.4.1 Aide a la mise au point : assert.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1178.4.2 Fonctions utilitaires : stdlib.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1188.4.3 Traitement de chanes :string.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1208.4.4 Classification des caracteres :ctype.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1218.4.5 Fonctions mathematiques :math.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121

    8.4.6 Limites propres a limplementation :limits.h

    ,float.h

    . . . . . . . . . . . . . . . . . . . 121

    Imprime le 4 mai 2006

    [email protected]

    4 c H. Garreta, 1988-2006

  • 5/21/2018 Le Langage C

    5/125

    1 ELEMENTS DE BASE

    1 Elements de base

    1.1 Structure generale dun programme

    La transformation dun texte ecrit en langage C en un programme executable par lordinateur se fait en deuxetapes : la compilationet ledition de liens. La compilation est la traduction des fonctions ecrites en C en des

    procedures equivalentes ecrites dans un langage dont la machine peut executer les instructions. Le compilateurlit toujours un fichier, appele fichier source, et produit unfichier, dit fichier objet.

    Chaque fichier objet est incomplet, insuffisant pour etre execute, car il contient des appels de fonctions ou desreferences a des variables qui ne sont pas definies dans le meme fichier. Par exemple, le premier programme quevous ecrirez contiendra deja la fonction printf que vous naurez certainement pas ecrite vous-meme. Leditionde liens est loperation par laquelle plusieurs fichiers objets sont mis ensemble pour se completer mutuelle-ment : un fichier apporte des definitions de fonctions et de variables auxquelles un autre fichier fait referenceet reciproquement. Lediteur de liens (ou linker) prend en entree plusieurs fichiers objets etbibliotheques (unevariete particuliere de fichiers objets) et produit un unique fichier executable. Lediteur de liens est largementindependant du langage de programmation utilise pour ecrire les fichiers sources, qui peuvent meme avoir eteecrits dans des langages differents.

    Chaque fichier source entrant dans la composition dun programme executable est fait dune succession dunnombre quelconque delements independants, qui sont :

    des directives pour le preprocesseur (lignes commencant par #), des constructions de types (struct, union, enum, typedef), des declarations de variables et de fonctions externes, des definitions de variables et des definitions de fonctions.

    Seules les expressions des deux dernieres categories font grossir le fichier ob jet : les definitions de fonc-tions laissent leur traduction en langage machine, tandis que les definitions de variables se traduisent par desreservations despace, eventuellement garni de valeurs initiales. Les autres directives et declarations sadressentau compilateur et il nen reste pas de trace lorsque la compilation est finie.

    En C on na donc pas une structure syntaxique englobant tout, comme la construction Program... end. du langage Pascal ; un programme nest quune collection de fonctions assortie dun ensemble de variablesglobales. Dou la question : par ou lexecution doit-elle commencer ? La regle generalement suivie par lediteurde liens est la suivante : parmi les fonctions donnees il doit en exister une dont le nom est main. Cest par elleque lexecution commencera ; le lancement du programme equivaut a lappel de cette fonction par le systemedexploitation. Notez bien que, a part cela, mainest une fonction comme les autres, sans aucune autre proprietespecifique ; en particulier, les variables internes a mainsont locales, tout comme celles des autres fonctions.

    Pour finir cette entree en matiere, voici la version C du celebre programme-qui-dit-bonjour, sans lequel onne saurait commencer un cours de programmation1 :

    #include

    int main() {

    printf("Bonjour\n");

    return 0;

    }

    1.2 Considerations lexicales

    1.2.1 Presentation du texte du programme

    Le programmeur est matre de la disposition du texte du programme. Des blancs, des tabulations et dessauts a la ligne peuvent etre places a tout endroit ou cela ne coupe pas un identificateur, un nombre ou unsymbole compose2.

    1Le programme montre ici est ecrit selon des regles strictes. En fait, la plupart des compilateurs acceptent quemainsoit declareevoid au lieu de int, ou que ce type ne figure pas, et que linstruction return 0; napparaisse pas explicitement.

    2Neanmoins, les directives pour le preprocesseur (cf. section 8.1) doivent comporter un # dans la premiere position de la ligne.Cela ne constitue pas une exception a la regle donnee ici, car le preprocesseur nest pas le compilateur C et ne travaille pas sur lasyntaxe du langage.

    c H. Garreta, 1988-2006 5

  • 5/21/2018 Le Langage C

    6/125

    1.2 Considerations lexicales 1 ELEMENTS DE BASE

    Les commentaires commencent par /*et se terminent par */:

    /* Ce texte est un commentaire et sera donc

    ignore par le compilateur */

    Les commentaires ne peuvent pas etre imbriques : ecrit dans un programme, le texte /* voici un grand/* et un petit */ commentaire */ est errone, car seul /* voici un grand /* et un petit */ seravu comme un commentaire par le compilateur.

    Les langages C et C++ cohabitant dans la plupart des compilateurs actuels, ces derniers acceptent egalementcomme commentaire tout texte compris entre le signe // et la fin de la ligne ou ce signe apparat :

    // Ceci est un commentaire a la mode C++.

    Le caractere anti-slash \ precedant immediatementun saut a la ligne masque ce dernier : la ligne suivanteest consideree comme devant etre concatenee a la ligne courante. Cela est vrai en toute circonstance, y comprisa linterieur dune chane de caracteres. Par exemple, le texte

    message = "anti\

    constitutionnellement";

    est compris comme ceci : message = "anti constitutionnellement" ;

    1.2.2 Mots-cles

    Les mots suivants sont reserves. Leur fonction est prevue par la syntaxe de C et ils ne peuvent pas etreutilises dans un autre but :

    auto break case char const continue default do

    double else enum extern float for goto if

    int long register return short signed sizeof static

    struct switch typedef union unsigned void volatile while

    1.2.3 Identificateurs

    Un identificateur est une suite de lettres et chiffres contigus, dont le premier est une lettre. Lorsque seulle compilateur est concerne, cest-a-dire lorsquil sagit didentificateurs dont la portee est incluse dans un seulfichier (nous dirons de tels identificateurs quils sont prives) :

    en toute circonstance une lettre ma juscule est tenue pour differente de la lettre minuscule correspondante ; dans les identificateurs, le nombre de caracteres discriminants est au moins de 31.Attention, lorsquil sagit didentificateurs externes, cest-a-dire partages par plusieurs fichiers sources, il est

    possible que sur un systeme particulier lediteur de liens sous-jacent soit trop rustique pour permettre le respectde ces deux prescriptions.

    Le caractere (appele blanc souligne

    ) est considere comme une lettre ; il p eut donc figurer a nimporte

    quelle place dans un identificateur. Cependant, par convention un programmeur ne doit pas utiliser des identi-ficateurs qui commencent par ce caractere. Cela assure quil ny aura jamais de conflit avec les noms introduits(a travers les fichiers

    .h

    ) pour les besoins des bibliotheques, car ces noms commencent par un tel blanc

    souligne.

    1.2.4 Operateurs

    Symboles simples :

    ( ) [ ] . ! ~ < > ? :

    = , + - * / % | & ^

    Symboles composes :

    -> ++ -- = == != && || >

    += -= *= /= %= = |= &= ^=

    Tous ces symboles sont reconnus par le compilateur comme des operateurs. Il est interdit dinserer descaracteres blancs a linterieur dun symbole compose. En outre, il est conseille dencadrer par des blancs touteutilisation dun operateur. Dans certaines circonstances cette regle est plus quun conseil, car sa non-observancecree une expression ambigue.

    6 c H. Garreta, 1988-2006

  • 5/21/2018 Le Langage C

    7/125

    1 ELEMENTS DE BASE 1.3 Constantes litterales

    1.3 Constantes litterales

    1.3.1 Nombres entiers

    Les constantes litterales numeriques entieres ou reelles suivent les conventions habituelles, avec quelquesparticularites.

    Les constantes litterales sont sans signe : lexpression123 est comprise comme lapplication de loperateurunaire a la constante 123 ; mais puisque le calcul est fait pendant la compilation, cette subtilite na aucuneconsequence pour le programmeur. Notez aussi quen C original, comme il nexiste pas doperateur + unaire, lanotation +123 est interdite.

    Les constantes litterales entieres peuvent aussi secrire en octal et en hexadecimal : une constante ecrite en octal (base 8) commence par 0 (zero) ; une constante ecrite en hexadecimal (base 16) commence par 0x ou 0X.Voici par exemple trois manieres decrire le meme nombre :

    27 033 0x1B

    Detail a retenir : on ne doit pas ecrire de zero non significatif a gauche dun nombre : 0123 ne representepas la meme valeur que 123.

    Le type dune constante entiere est le plus petit type dans lequel sa valeur peut etre representee. Ou, plusexactement :

    si elle est decimale : si possible int, sinon long, sinon unsigned long ; si elle est octale ou hexadecimale : si possible int, sinon unsigned int, sinon unsigned long.Certains suffixes permettent de changer cette classification : U, u: indique que la constante est dun type unsigned ; L, l: indique que la constante est dun type long.Exemples : 1L, 0x7FFFU. On peut combiner ces deux suffixes : 16UL.

    1.3.2 Nombres flottants

    Une constante litterale est lexpression dun nombre flottant si elle presente, dans lordre : une suite de chiffres decimaux (la partie entiere), un point, qui joue le role de virgule decimale, une suite de chiffres decimaux (la partie fractionnaire), une des deux lettresE ou e, eventuellement un signe + ou -, une suite de chiffres decimaux.Les trois derniers elements forment lexposant. Exemple : 123.456E-78.

    On peut omettre : la partie entiere ou la partie fractionnaire, mais pas les deux, le point ou lexposant, mais pas les deux.Exemples : .5e7, 5.e6, 5000000., 5e6

    Une constante flottante est supposee de type double, a moins de comporter un suffixe explicite : les suffixes Fou f indiquent quelle est du type float ; les suffixes Lou l indiquent quelle est du type long double.Exemples : 1.0L, 5.0e4f

    1.3.3 Caracteres et chanes de caracteres

    Une constante de type caractere se note en ecrivant le caractere entre apostrophes. Une constante de typechane de caracteres se note en ecrivant ses caracteres entre guillemets. Exemples, trois caracteres :

    A 2 "

    Quatre chanes de caracteres :"A" "Bonjour a tous !" "" ""

    On peut faire figurer nimporte quel caractere, meme non imprimable, dans une constante caractere ouchane de caracteres en utilisant les combinaisons suivantes, appelees sequences dechappement :

    c H. Garreta, 1988-2006 7

  • 5/21/2018 Le Langage C

    8/125

    1.3 Constantes litterales 1 ELEMENTS DE BASE

    \n nouvelle ligne (LF)\t tabulation (HT)\b espace-arriere (BS)\r retour-chariot (CR)\f saut de page (FF)\a signal sonore (BELL)\\ \

    " "

    \d3d2d1 le caractere qui a pour code le nombre octald3d2d1. Sil commence par un ou deux zeroset si cela ne cree pas une ambigute, on peut aussi le noter \d2d1 ou \d1

    Par exemple, la chane suivante definit la suite des 9 caracteres3 A, escape(de code ASCII 27), B, , C, sautde page, D, \ et E :

    "A\033B\"C\fD\\E"

    Une constante de type caractere appartient au type char, cest-a-dire entier represente sur un octet. Lavaleur dune constante caractere est le nombre qui represente le caractere de maniere interne ; de nos jours ilsagit presque toujours du code ASCII4.

    Une constante de type chane de caracteres represente une suite finie de caracteres, de longueur quelconque.Le codage interne dune chane de caracteres est le suivant (voyez la figure 1) : les caracteres constituant la chane sont ranges en memoire, de maniere contigue, dans lordre ou ils

    figurent dans la chane ; un caractere nul est ajoute immediatement apres le dernier caractere de la chane, pour en indiquer la fin ; la constante chane represente alors, a lendroit ou elle est ecrite, ladressede la cellule ou a ete range le

    premier caractere de la chane.

    B n j u ro 0\o

    "Bonjour"

    Fig. 1 Representation de la chane "Bonjour"

    Par consequent, une constante chane de caracteres a pour type celui dun tableau de caracteres (cest-a-dire char[] ) et pour valeur ladresse dune cellule de la memoire.

    Par caractere nul on entend le caractere dont le code interne est 0 ; on peut le noter indifferemment 0,\000ou \0 (mais certainement pas 0) ; il est utilise tres frequemment en C. Notez que, dans une expression,\0est toujours interchangeable avec 0.

    1.3.4 Expressions constantes

    Une expression constante est une expression de lun des types suivants : toute constante litterale ; exemples : 1, A, "HELLO", 1.5e-2 ; une expression correcte formee par lapplication dun operateur courant (arithmetique, logique, etc.) a une

    ou deux expressions constantes ; exemples : -1, A - a, 2 * 3.14159265, "HELLO" + 6 ; lexpression constituee par lapplication de loperateur & (operateur de calcul de ladresse, voyez la sec-

    tion 2.2.10) a une variable statique, a un champ dune variable statique de type structure ou a un elementdun tableau statique dont le rang est donne par une expression constante ; exemples : &x, &fiche.nom,&table[50] ;

    lexpression constituee par lapplication de loperateur sizeof a un descripteur de type. Exemples :sizeof(int), sizeof(char *) ;

    lexpression constituee par lapplication de loperateur sizeof a une expression quelconque, qui ne serapas evaluee ; exemples : sizeof x, sizeof(2 * x + 3).

    Les expressions constantes peuvent etre evaluees pendant la compilation. Cela est fait a titre facultatif par

    les compilateurs de certains langages. En C ce nest pas facultatif : il est garanti que toute expression constante(et donc toute sous-expression constante dune expression quelconque) sera effectivement evaluee avant que

    3Nous verrons quen fait cette chane comporte un caractere de plus qui en marque la fin.4En standard le langage C ne prevoit pas le codage Unicodedes caracteres.

    8 c H. Garreta, 1988-2006

  • 5/21/2018 Le Langage C

    9/125

    1 ELEMENTS DE BASE 1.4 Types fondamentaux

    lexecution ne commence. En termes de temps dexecution, levaluation des expressions constantes est doncentierement gratuite .

    1.4 Types fondamentaux

    Types de base

    Nombres entiersAnonymes

    Petite taille signes char non signes unsigned char

    Taille moyenne signes short non signes unsigned short

    Grande taille signes long non signes unsigned long

    Nommes

    enumNombres flottantsSimples floatGrande precision doublePrecision encore plus grande long double

    Types derives

    Tableaux [ ]Fonctions ( )Pointeurs *Structures structUnions union

    Tab. 1 Les types du langage C

    Le tableau 1 presente lensemble des types connus du compilateur C. Lorganisation generale de cet ensembleest evidente : on dispose de deux sortes de types de base, les nombres entiers et les nombres flottants, et dunefamille infinie de types derives obtenus en appliquant quelques procedes recursifs de construction soit a destypes fondamentaux soit a des types derives definis de la meme maniere.

    Cette organisation revele un trait de lesprit de C : le pragmatisme lemporte sur lesthetisme, parfois memesur la rigueur. Dans dautres langages, les caracteres, les booleens, les constantes symboliques, etc., sont codesde maniere interne par des nombres, mais ce fait est officiellement ignore par le programmeur, qui reste obligede considerer ces donnees comme appartenant a des ensembles disjoints. En C on a fait le choix oppose, laissantau programmeur le soin de realiser lui-meme, a laide des seuls types numeriques, limplantation des types de

    niveau superieur.

    1.4.1 Nombres entiers et caracteres

    La classification des types numeriques obeit a deux criteres :

    Si on cherche a representer un ensemble de nombres tous positifs on pourra adopter un typenon signe;au contraire si on doit representer un ensemble contenant des nombres positifs et des nombres negatifs ondevra utiliser un type signe5.

    Le deuxieme critere de classification des donnees numeriques est la taille requise par leur representation.Comme precedemment, cest un attribut dun ensemble, et donc dune variable devant representer toutelement de lensemble, non dune valeur particuliere. Par exemple, le nombre 123 considere comme un

    element de lensemble{0 ... 65535} est plus encombrant que le meme nombre 123 quand il est considerecomme un element de lensemble{0 ... 255}.5On dit parfois quune donnee est un entier signe ou est un entier non signe . Cest un abus de langage : le caractere signe

    ou non signe nest pas un attribut dun nombre (un nombre donne est positif ou negatif, cest tout) mais de lensemble de nombresquon a choisi de considerer et, par extension, de toute variable censee pouvoir representer nimporte quelle valeur de cet ensemble.

    c H. Garreta, 1988-2006 9

  • 5/21/2018 Le Langage C

    10/125

    1.4 Types fondamentaux 1 ELEMENTS DE BASE

    Avec N chiffres binaires (ou bits) on peut representer : soit les 2N nombres positifs 0, 1,... 2N 1 (cas non signe) ; soit les 2N nombres positifs et negatifs2N1,... 2N1 1 (cas signe).De plus, la representation signee et la representation non signee des elements communs aux deux domaines

    (les nombres 0, 1,... 2N1 1) concident.Le type caractere. Un objet de type char peut etre defini, au choix, comme un nombre entier pouvant representer nimporte quel caractere du jeu de caracteres de la machine utilisee ; un nombre entier occupant la plus petite cellule de memoire adressable separement6. Sur les machines

    actuelles les plus repandues cela signifie generalement un octet (8 bits).

    Le plus souvent, un char est un entier signe ; un unsigned charest alors un entier non signe. Lorsque lescharsont par defaut non signes, la norme ANSI prevoit la possibilite de declarer des signed char.

    On notera que la signification duncharen C, un entier petit, est tres differente de celle dun charen Pascal(dans ce langage, lensemble des caracteres et celui des nombres sont disjoints). En C, ch etant une variable detype char, rien ne soppose a lecriture de lexpression ch - A + 32 qui est tout a fait homogene, puisqueentierement faite de nombres.

    Le caractere impossible . Toutes les valeurs quil est possible de ranger dans une variable de typechar sont en principe des caracteres legaux. Or la plupart des programmes qui lisent des caracteres doivent

    etre capables de manipuler une valeur supplementaire, distincte de tous les

    vrais

    caracteres, signifiant

    lafin des donnees . Pour cette raison, les variables et fonctions qui representent ou renvoient des caracteres sontsouvent declarees int, non char : nimporte quelle valeur appartenant au type intmais nappartenant pas autype char peut alors servir dindicateur de fin de donnees. Par exemple, une telle valeur est definie dans lefichier stdio.h, cest la constante symbolique EOF.

    Les entiers courts et longs. Il est garanti que toute donnee representable dans le type short estrepresentable aussi dans le type long7 (en bref : un long nest pas plus court quun short !), mais la tailleexacte des donnees de ces types nest pas fixee par la norme du langage.

    De nos jours on trouve souvent :

    unsigned short : 16 bits pour representer un nombre entier compris entre 0 et 65.535short : 16 bits pour representer un nombre entier compris entre -32.768 et 32.767unsigned long : 32 bits pour representer un nombre entier entre 0 et 4.294.967.296long : 32 bits pour representer un entier entre -2.147.483.648 et 2.147.483.647

    Le type int. En principe, le type int correspond a la taille dentier la plus efficace, cest-a-dire la plusadaptee a la machine utilisee. Sur certains systemes et compilateurs int est synonyme de short, sur dautres ilest synonyme de long.

    Le type int peut donc poser un probleme de portabilite8 : le meme programme, compile sur deux machinesdistinctes, peut avoir des comportements differents. Dou un conseil important : nutilisez le type int que pourdes variables locales destinees a contenir des valeurs raisonnablement petites (inferieures en valeur absolue a32767) . Dans les autres cas il vaut mieux expliciter char, short ou long selon le besoin.

    A propos des booleens. En C il nexiste donc pas de type booleen specifique. Il faut savoir qua toutendroit ou une expression booleenne est requise (typiquement, dans des instructions comme if ou while) on

    peut faire figurer nimporte quelle expression ; elle sera tenue pour vraie si elle est non nulle, elle sera considereefausse sinon. Ainsi, dans un contexte conditionnel,expr

    (cest-a-direexpr vraie ) equivaut aexpr!= 0

    (exprdifferente de 0). Inversement, lorsquun operateur (egalite, comparaison, etc.) produit une valeur booleenne,

    6A retenir : un objet de type charest unitaire aussi bien du point de vue des tailles que de celui des adresses. Quelle que soitla machine utilisee, le compilateur C fera en sorte que le programmeur voie ces objets de la maniere suivante : si t est un tableaude char, la taille (au sens de loperateursizeof, cf. section 2.2.11) de t[0]vaut une unite de taille, et lecart entre les adresses det[1]et t[0]vaut une unite dadressage. On peut dire que ces proprietes d efinissentle type char (ou, si vous preferez, les unites detaille et dadressage).

    7Si on considere un type comme lensemblede ses valeurs, on a donc les inclusions larges char short long (et aussi float double long double).

    8

    Un programme ecrit pour une machine ou un systemeA est dit portable sil suffit de le recompiler pour quil tourne correctementsur une machine differente B. Par exemple, putchar(A) ; est une maniere portable dobtenir laffichage du caractere A, tandisque putchar(65) ; est (sur un systeme utilisant le code ASCII) une maniere non portable dobtenir le meme affichage. Etreportable est un critere de qualite et de fiabilite important. On invoque lefficacite pour justifier lecriture de programmes nonportables ; lexperience prouve que, lorsque son ecriture est possible, un programme portable est toujours meilleur quun programmenon portable pretendu equivalent.

    10 c H. Garreta, 1988-2006

  • 5/21/2018 Le Langage C

    11/125

    1 ELEMENTS DE BASE 1.5 Variables

    il rend 0 pour faux et 1 pour vrai.

    Signalons aux esthetes que le fichier comporte les declarations :

    enum { false, true };

    typedef unsigned char Boolean;

    qui introduisent la constante false valant 0, la constante true valant 1 et le type Boolean comme le type lemoins encombrant dans lequel on peut representer ces deux valeurs.

    1.4.2 Typ es enumeres

    Un type enumere, ou enumeration, est constitue par une famille finie de nombres entiers, chacun associea un identificateur qui en est le nom. Mis a part ce qui touche a la syntaxe de leur declaration, il ny a pasgrand-chose a dire a leur sujet. La syntaxe de la declaration des enumerations est expliquee a la section 5.3. Parexemple, lenonce :

    enum jour_semaine { lundi, mardi, mercredi, jeudi, vendredi, samedi, dimanche };

    introduit un type enumere, appele enum jour semaine, constitue par les constantes lundi valant 0, mardivalant 1, mercredi valant 2, etc. Ainsi, les expressions mardi + 2 et jeudi representent la meme valeur.

    Les valeurs dun type enumere se comportent comme des constantes entieres ; elles font donc double emploi

    avec celles quon definit a laide de #define (cf. section 8.1.2). Leur unique avantage reside dans le fait quecertains compilateurs detectent parfois, mais ce nest pas exige par la norme, les melanges entre ob jets de typesenumeres distincts ; ces types sont alors le moyen daugmenter la securite des programmes.

    A propos des types enumeres voyez aussi la section 5.3.

    1.4.3 Nombres flottants

    La norme ANSI prevoit trois types de nombres flottants :float(simple precision),double(double precision)et long double(precision etendue). La norme ne specifie pas les caracteristiques de tous ces types. Il est garantique toute valeur representable dans le typefloatest representable sans perte dinformation dans le typedouble,et toute valeur representable dans le type double lest dans le type long double.

    Typiquement, sur des systemes de taille moyenne, un float occupe 32 bits et un double 64, ce qui donnepar exemple des float allant de -1.70E38 a -0.29E-38 et de 0.29E-38 a 1.70E38 avec 7 chiffres decimauxsignificatifs, et des double allant de -0.90E308 a -0.56E-308 et de 0.56E-308 a 0.90E308 avec 15 chiffresdecimaux significatifs.

    Les long double correspondent generalement aux flottants de grande precision manipules par certainscoprocesseurs arithmetiques ou les bibliotheques de sous-programmes qui les simulent. Mais il nest pas excluque sur un systeme particulier un long double soit la meme chose quun double.

    1.5 Variables

    1.5.1 Syntaxe des declarations

    La forme complete de la declaration dune variable sera expliquee a la section 5.4. Dans le cas le plus simpleon trouve

    specification var-init , var-init , ... var-init;

    ou specification est de la forme :

    auto

    register

    static

    extern

    rien

    const

    volatile

    rien

    unsigned

    signed

    rien

    char

    short

    long

    int

    float

    double

    long double

    et chaque var-initest de la forme :

    identificateur

    = expression

    rien

    c H. Garreta, 1988-2006 11

  • 5/21/2018 Le Langage C

    12/125

    1.5 Variables 1 ELEMENTS DE BASE

    Exemples :

    int x, y = 0, z;

    extern float a, b;

    static unsigned short cpt = 1000;

    Les declarations de variables peuvent se trouver : en dehors de toute fonction, il sagit alors devariables globales;

    a linterieur dun bloc, il sagit alors devariables locales; dans len-tete dune fonction, il sagit alors darguments formels, places soit dans les parentheses de len-tete (fonction definie en syntaxe ANSI avec un prototype), soit entre le nom de la fonction et le{initial (fonction definie en syntaxe originale ou sans prototype).

    Exemple. Avec prototype :

    long i = 1;

    int une_fonction(int j) {

    short k;

    ...

    }

    Sans prototype :

    long i = 1;

    int une_fonction(j)

    int j;

    {

    short k;

    ...

    }

    Ci-dessus,i est une variable globale, kune variable locale et jun argument formel de une fonction.

    1.5.2 Visibilite des variables

    La question de la visibilite des identificateurs (cest-a-dire quels sont les identificateurs auxquels on peutfaire reference en un point dun programme ? ) est reglee en C comme dans la plupart des langages comportantla structure de bloc, avec une simplification : les fonctions ne peuvent pas etre imbriquees les unes dans lesautres, et une complication : tout bloc peut comporter ses propres definitions de variables locales.

    Un bloc est une suite de declarations et dinstructions encadree par une accolade ouvrante { et laccoladefermante } correspondante. Le corps dune fonction est lui-meme un bloc, mais dautres blocs peuvent etreimbriques dans celui-la.

    Variables locales. Tout bloc peut comporter un ensemble de declarations de variables, qui sont alorsdites localesau bloc en question. Une variable locale ne peut etre referencee que depuis linterieur du bloc ouelle est definie ; en aucun cas on ne peut y faire reference depuis un point exterieur a ce bloc. Dans le bloc ou il

    est declare, le nom dune variable locale masquetoute variable de meme nom definie dans un bloc englobant lebloc en question.

    Toutes les declarations de variables locales a un bloc doivent etre ecrites au debut du bloc, avant la premiereinstruction.

    Arguments formels. Pour ce qui concerne leur visibilite, les arguments formels des fonctions sont considerescomme des variables locales du niveau le plus haut, cest-a-dire des variables declarees au debut du bloc le plusexterieur9. Un argument formel est accessible de linterieur de la fonction, partout ou une variable locale plusprofonde ne le masque pas. En aucun cas on ne peut y faire reference depuis lexterieur de la fonction.

    Variables globales. Le nom dune variable globale ou dune fonction peut etre utilise depuis nimportequel point compris entre sa declaration (pour une fonction : la fin de la declaration de son en-tete) et la findu fichier ou la declaration figure, sous reserve de ne pas etre masquee par une variable locale ou un argument

    formel de meme nom.La question de la visibilite inter-fichiers est examinee a la section 1.6. On peut noter dores et deja quelle ne

    se pose que pour les variables globales et les fonctions, et quelle concerne ledition de liens, non la compilation,

    9Par consequent, on ne doit pas declarer un argument formel et une variable locale du niveau le plus haut avec le meme nom.

    12 c H. Garreta, 1988-2006

  • 5/21/2018 Le Langage C

    13/125

    1 ELEMENTS DE BASE 1.5 Variables

    car le compilateur ne traduit quun fichier source a la fois et, pendant la traduction dun fichier, il ne voit

    pas les autres.

    1.5.3 Allocation et duree de vie des variables

    Les variables globales sont toujours statiques, cest-a-dire permanentes : elles existent pendant toute la

    duree de lexecution. Le systeme dexploitation se charge, immediatement avant lactivation du programme, deles allouer dans un espace memoire de taille adequate, eventuellement garni de valeurs initiales.

    A loppose, les variables locales et les arguments formels des fonctions sontautomatiques: lespace corres-pondant est alloue lors de lactivation de la fonction ou du bloc en question et il est rendu au systeme lorsquele controle quitte cette fonction ou ce bloc. Certains qualifieurs (static, register, voir les sections 1.5.5 et1.5.6) permettent de modifier lallocation et la duree de vie des variables locales.

    Remarque. On note une grande similitude entre les variables locales et les arguments formels des fonctions :ils ont la meme visibilite et la meme duree de vie. En realite cest presque la meme chose : les arguments formelssont de vraies variables locales avec lunique particularite detre automatiquement initialises (par les valeurs desarguments effectifs) lors de lactivation de la fonction.

    1.5.4 Initialisation des variables

    Variables statiques. En toute circonstance la declaration dune variable statique peut indiquer une valeurinitiale a ranger dans la variable. Cela est vrai y compris pour des variables de types complexes (tableaux oustructures). Exemple :

    double x = 0.5e3;

    int t[5] = { 11, 22, 33, 44, 55 };

    Bien que la syntaxe soit analogue, une telle initialisation na rien en commun avec une affectation commecelles qui sont faites durant lexecution du programme. Il sagit ici uniquement de preciser la valeur qui doitetre deposee dans lespace alloue a la variable, avant que lexecution ne commence. Par consequent :

    la valeur initiale doit etre definie par une expression constante (calculable durant la compilation) ; une telle initialisation est entierement gratuite, elle na aucune incidence ni sur la taille ni sur la duree du

    programme executable produit.

    Les variables statiques pour lesquelles aucune valeur initiale nest indiquee sont remplies de zeros. Lin-terpretation de ces zeros depend du type de la variable.

    Variables automatiques. Les arguments formels des fonctions sont automatiquement initialises lors deleur creation (au moment de lappel de la fonction) par les valeurs des arguments effectifs. Cela est la definitionmeme des arguments des fonctions.

    La declaration dune variable locale peut elle aussi comporter une initialisation. Mais il ne sagit pas de lameme sorte dinitialisation que pour les variables statiques : linitialisation represente ici une affectation tout afait ordinaire. Ainsi, placee a linterieur dun bloc, la construction

    int i = exp; /* declaration + initialisation */

    equivaut au couple

    int i; /* declaration */

    ...

    i = exp; /* affectation */

    Par consequent : lexpression qui donne la valeur initiale na pas a etre constante, puisquelle est evaluee a lexecution,

    chaque fois que la fonction ou le bloc est active ; une telle initialisation coute le meme prix que laffectation correspondante, cest-a-dire le temps

    devaluation de lexpression qui definit la valeur initiale.

    Les variables automatiques pour lesquelles aucune valeur initiale nest indiquee sont allouees avec une valeurimprevisible.

    Remarque. Dans le C original, une variable automatique ne peut etre initialisee que si elle est simple(cest-a-dire autre que tableau ou structure). Cette limitation ne fait pas partie du C ANSI.

    c H. Garreta, 1988-2006 13

  • 5/21/2018 Le Langage C

    14/125

    1.5 Variables 1 ELEMENTS DE BASE

    1.5.5 Variables locales statiques

    Le qualifieur static, place devant la declaration dune variable locale, produit une variable qui est pour sa visibilite, locale ; pour sa duree de vie, statique (cest-a-dire permanente).

    Elle nest accessible que depuis linterieur du bloc ou elle est declaree, mais elle est creee au debut delactivation du programme et elle existe aussi longtemps que dure lexecution de celui-ci. Exemple :

    void bizarre1(void) {

    static int cpt = 1000;

    printf("%d ", cpt);

    cpt++;

    }

    Lorsque la declaration dune telle variable comporte une initialisation, il sagit de linitialisation dune va-riable statique : elle est effectuee une seule fois avant lactivation du programme. Dautre part, une variablelocale statique conserve sa valeur entre deux activations consecutives de la fonction. Ainsi, des appels successifsde la fonction ci-dessus produisent laffichage des valeurs 1000, 1001, 1002, etc. On aurait pu obtenir un effetanalogue avec le programme

    int cpt = 1000;

    void bizarre2(void) {

    printf("%d ", cpt);

    cpt++;

    }

    mais ici la variable cpt est globale et peut donc etre modifiee inconsiderement par une autre fonction, ou entreren conflit avec un autre ob jet de meme nom, tandis que dans la premiere version elle nest visible que depuislinterieur de la fonction et donc a labri des manipulations maladroites et des collisions de noms. On noterapour finir que la version suivante est erronee :

    void bizarre3(void) {

    int cpt = 1000;

    printf("%d ", cpt);

    cpt++;

    }

    En effet, tous les appels de bizarre3 afficheront la meme valeur 1000.

    Attention. Malgre tout le bien quon vient den dire, les variables locales statiques ont une particularitepotentiellement fort dangereuse : il en existe une seule instancepour toutes les activations de la fonction danslaquelle elles sont declarees. Ainsi, dans lexemple suivant :

    void fonction_suspecte(void) {

    static int i;

    ...

    fonction_suspecte();

    ...

    }

    la valeur de la variable i avant et apres lappel de fonction suspecte (cest-a-dire aux points et ) peutne pas etre la meme, car la deuxieme activation de fonction suspecte accede aussi a i. Cela est tout a faitinhabituel pour une variable locale. Consequence a retenir : les variables locales statiques se marient mal avecla recursivite.

    1.5.6 Variables critiques

    Le qualifieur register precedant une declaration de variable informe le compilateur que la variable enquestion est tres frequemment accedee pendant lexecution du programme et quil y a donc lieu de prendretoutes les dispositions utiles pour en accelerer lacces. Par exemple, dans certains calculateurs de telles variables

    sont logees dans un registre de lunite centrale de traitement (CPU) plutot que dans la memoire centrale ; decette maniere lacces a leur valeur ne met pas en uvre le busde la machine.

    Les variables ainsi declarees doivent etrelocaleset dun type simple(nombre, pointeur). Elles sont automa-tiquement initialisees a zero chaque fois quelles sont creees. Le compilateur accorde ce traitement special aux

    14 c H. Garreta, 1988-2006

  • 5/21/2018 Le Langage C

    15/125

    1 ELEMENTS DE BASE 1.6 Variables, fonctions et compilation separee

    variables dans lordre ou elles figurent dans les declarations. Lorsque cela nest plus possible (par exemple, parceque tous les registres de la CPU sont pris) les declarationsregister restantes sont ignorees. Il convient doncdappliquer ce qualifieur aux variables les plus critiques dabord. Exemple :

    char *strcpy(char *dest, char *srce) {

    register char *d = dest, *s = srce;

    while ((*d++ = *s++) != 0)

    ;

    return dest;

    }

    Attention. Lutilisation du qualifieur register est interessante lorsque lon doit utiliser un compilateurrustique, peu

    optimisateur

    . Or de nos jours les compilateurs de C ont fini par devenir tres perfectionnes et

    integrent des algorithmes doptimisation, parmi lesquels la determination des variables critiques et leur allocationdans les registres de la CPU. Il savere alors que le programmeur, en appliquant le qualifieurregister a sesvariables preferees (quil croit critiques alors quelles ne le sont pas reellement), gene le travail du compilateuret obtient un programme moins efficace que sil navait jamais utilise ce qualifieur.

    1.5.7 Variables constantes et volatiles

    Le qualifieurconstplace devant une variable ou un argument formel informe le compilateur que la variableou largument en question ne changera pas de valeur tout au long de lexecution du programme ou de lactivationde la fonction. Ce renseignement permet au compilateur doptimiser la gestion de la variable, la nature exactedune telle optimisation netant pas specifiee. Par exemple un compilateur peut juger utile de ne pas allouerdu tout une variable qualifiee const et de remplacer ses occurrences par la valeur initiale10 indiquee lors de ladeclaration. Il est conseille de toujours declarer const les variables et les arguments formels qui peuvent letre.

    Note. Cest regrettable mais, pour la plupart des compilateurs, une variable qualifiee constnest pas touta fait une expression constante au sens de la section 1.3.4. En particulier, pour ces compilateurs une variable,meme qualifiee const, ne peut pas etre utilisee pour indiquer le nombre delements dans une declaration detableau.

    Le C ANSI introduit aussi les notions de pointeur constant et de pointeur sur constante, expliquees a la

    section 5.4.2.

    Le sens du qualifieurvolatiledepend lui aussi de limplementation. Il diminue le nombre dhypotheses, etdonc doptimisations, que le compilateur peut faire sur une variable ainsi qualifiee. Par exemple toute variabledont la valeur peut etre modifiee de maniere asynchrone (dans une fonction de detection dinterruption, ou parun canal dentree-sortie, etc.) doit etre qualifiee volatile, sur les systemes ou cela a un sens. Cela previentle compilateur que sa valeur peut changer mysterieusement, y compris dans une section du programme qui necomporte aucune reference a cette variable.

    Les compilateurs sont tenus de signaler toute tentative decelable de modification dune variable const. Misa part cela, sur un systeme particulier ces deux qualifieurs peuvent navoir aucun autre effet. Ils nappartiennentpas au C original.

    1.6 Variables, fonctions et compilation separee

    1.6.1 Identificateurs publics et prives

    Examinons maintenant les regles qui regissent la visibilite inter-fichiers des identificateurs. La question neconcerne que les noms de variables et de fonctions, car les autres identificateurs (noms de structures, de types,etc.) nexistent que pendant la compilation et ne peuvent pas etre partages par deux fichiers. Il ny a pas deprobleme pour les variables locales, dont la visibilite se reduit a letendue de la fonction ou du bloc contenantleur definition. Il ne sera donc question que des noms des variables globales et des noms des fonctions.

    Jargon. Identificateurs publics et prives. Un nom de variable ou de fonction defini dans un fichier source etpouvant etre utilise dans dautres fichiers sources est dit public. Un identificateur qui nest pas public est appele

    prive.Regle 1.

    10La declaration dune variable const doit necessairement comporter une initialisation car sinon, une telle variable ne pouvantpas etre affectee par la suite, elle naurait jamais de valeur definie.

    c H. Garreta, 1988-2006 15

  • 5/21/2018 Le Langage C

    16/125

    1.6 Variables, fonctions et compilation separee 1 ELEMENTS DE BASE

    Sauf indication contraire, tout identificateur global est public ; le qualifieurstatic, precedant la declaration dun identificateur global, rend celui-ci prive.

    On prendra garde au fait que le qualifieurstaticna pas le meme effet quand il sapplique a un identificateurlocal (staticchange la duree de vie, dautomatique en statique, sans toucher a la visibilite) et quand il sappliquea un identificateur global (staticchange la visibilite, de publique en privee, sans modifier la duree de vie).

    Lorsquun programme est decompose en plusieurs fichiers sources il est fortement conseille, pour ne pas dire

    obligatoire, dutiliser le qualifieur static pour rendre prives tous les identificateurs qui peuvent letre. Si on nesuit pas cette recommandation on verra des fichiers qui etaient corrects separement devenir errones lorsquilssont relies, uniquement parce quils partagent a tort des identificateurs publics.

    1.6.2 Declaration dobjets externes

    Nous ne considerons donc desormais que les noms publics. Un identificateur reference dans un fichier alorsquil est defini dans un autre fichier est appeleexterne. En general, les noms externes doivent faire lobjet dunedeclaration : le compilateur ne traitant quun fichier a la fois, les proprietes de lobjet externe doivent etreindiquees pour que la compilation puisse avoir lieu correctement.

    Jargon. Definition et declaration dune variable ou dune fonction. Aussi bien une declaration quune

    definition dun nom de variable ou de fonction est une formule qui specifie la classe syntaxique (variable oufonction) et les attributs (type, valeur initiale, etc.) de lidentificateur en question. En plus de cela :

    une definitionproduit la creation de lobjet dont lidentificateur est le nom ; une declaration se limite a indiquer que lobjet en question a du etre cree dans un autre fichier qui sera

    fourni lors de ledition de liens.

    ( Creer une variable ou une fonction cest reserver lespace correspondant, rempli par leventuelle valeurinitiale de la variable ou par le code de la fonction).

    Regle 2. Toute variable doit avoir ete definie (cest-a-dire declaree normalement) ou declaree externe avant son

    utilisation ; une fonction peut etre referencee alors quelle na encore fait lobjet daucune definition ni declaration

    externe ; elle est alors supposee etre externe, a resultat entier (int), sans prototype (cf. section 4.2) ;

    par consequent, si une fonction nest pas a resultat entier alors elle doit etre soit definie soit declareeexterne avant son appel, meme si elle est ulterieurement definie dans le fichier ou figure lappel.

    La declaration externe dune variable sobtient en faisant preceder une declaration ordinaire du mot-cleextern. Exemple :

    extern unsigned long n;

    Dans un autre fichier cette variable aura ete definie :

    unsigned long n;

    La declaration externe dune variable doit etre identique, au mot extern pres, a sa definition. Sauf pour lesdeux points suivants :

    une declaration externe ne doit pas comporter dinitialisateur (puisque la declaration externe nalloue pasla variable),

    dans une declaration externe de tableau, il est inutile dindiquer la taille de celui-ci (puisque la declarationexterne nalloue pas le tableau).

    Exemple. Dans le fichier ou sont definies les variables n et table, on ecrira :

    unsigned long n = 1000;

    int table[100];

    Dans un autre fichier, ou ces variables sont uniquement referencees, on ecrira :

    extern unsigned long n;extern int table[];

    La declaration externe dune fonction sobtient en ecrivant len-tete de la fonction, precede du mot externet suivi dun point-virgule ; le mot externest facultatif. Exemple : definition de la fonction

    16 c H. Garreta, 1988-2006

  • 5/21/2018 Le Langage C

    17/125

    1 ELEMENTS DE BASE 1.6 Variables, fonctions et compilation separee

    double carre(double x) {

    return x * x;

    }

    Declaration externe dans un autre fichier :

    double carre(double x);

    ou

    double carre(double);

    ou lun ou lautre de ces enonces, precede du mot extern.

    En syntaxe originale (cest-a-dire sans prototype ) il faut en outre ne pas ecrire les arguments formels.Definition :

    double carre(x)

    double x;

    {

    return x * x;

    }

    Declaration externe dans un autre fichier :

    double carre();

    Regle 3. Dans lensemble des fichiers qui constituent un programme, chaque nom public : doit faire lobjet dune et une seule definition ; peut etre declare externe (y compris dans le fichier ou il est defini) un nombre quelconque de fois.

    Cette regle volontariste est simple et elle exprime la meilleure facon de programmer. Il faut savoir cependantque chaque systeme tolere des ecarts, qui revelent surtout la rusticite de lediteur de liens sous-jacent. La clartedes concepts et la fiabilite des programmes y perdent beaucoup.

    Un comportement frequent est le suivant : appelons momentanement declaration-definition une expressiongenerale de la forme

    externopt declaration = initialisateur

    rien

    ;

    Nous pouvons donner la regle relachee :

    Regle 3. Dans lensemble des fichiers qui constituent un programme, chaque nom public peut faire lobjetdun nombre quelconque de declarations-definitions, mais :

    il doit y avoir au moins une declaration-definition sans le mot-cle extern ; il peut y avoir au plus une declaration-definition comportant un initialisateur.

    Des techniques et conseils pour ecrire des programmes modulaires en C sont exposes a la section 8.2.

    c H. Garreta, 1988-2006 17

  • 5/21/2018 Le Langage C

    18/125

    2 OPERATEURS ET EXPRESSIONS

    2 Operateurs et expressions

    2.1 Generalites

    Dans cette section nous etudions les operateurs et les expressions du langage C. Les expressions simples sontles constantes litterales (0,A,0.31416e1, etc.), les constantes symboliques (lundi,false, etc.) et les noms de

    variables (x,nombre, etc.). Les operateurs servent a construire des expressions complexes, comme 2 * x + 3 ousin(0.31416e1). Les proprietes dune expression complexe decoulent essentiellement de la nature de loperateurqui chapeaute lexpression.

    On peut distinguer les expressionspuresdes expressionsavec effet de bord11. Dans tous les cas une expressionrepresente une valeur. Une expression pure ne fait que cela : letat du systeme est le meme avant et apres sonevaluation. Au contraire, une expression a effet de bord modifie le contenu dune ou plusieurs variables. Parexemple, lexpressiony + 1est pure, tandis que laffectation x = y + 1 (qui en C est une expression) est a effetde bord, car elle modifie la valeur de la variable x. Comme nous le verrons, en C un grand nombre dexpressionsont de tels effets.

    Remarque 1. Les operateurs dont il sera question ici peuvent aussi apparatre dans les declarations, pourla construction des types derives (tableaux, pointeurs et fonctions) comme dans la declaration complexe :

    char (*t[20])();

    La signification des expressions ainsi ecrites est alors tres differente de celle des expressions figurant dans lapartie executable des programmes, mais on peut signaler dores et deja que toutes ces constructions obeissent auxmemes regles de syntaxe, notamment pour ce qui concerne la priorite des operateurs et lusage des parentheses.La question des declarations complexes sera vue a la section 5.4.

    Remarque 2. Cest une originalite de C que de considerer les designateurs complexes (les objets pointes,les elements des tableaux, les champs des structures, etc.) comme des expressions construites avec des operateurset obeissant a la loi commune, notamment pour ce qui est des priorites. On se souvient quen Pascal les signesqui permettent decrire de tels designateurs (cest-a-dire les selecteurs[],^ et .) nont pas statut doperateur. Ilne viendrait pas a lidee dun programmeur Pascal decrire 2 + (t[i])afin de lever une quelconque ambigutesur la priorite de + par rapport a celle de [], alors quen C de telles expressions sont habituelles. Bien sur, dans2 + (t[i]) les parentheses sont superflues, car la priorite de loperateur [] est superieure a celle de +, mais ce

    nest pas le cas dans (2 + t)[i], qui est une expression egalement legitime.

    2.1.1 Lvalue et rvalue

    Toute expression possede au moins deux attributs : un type et une valeur. Par exemple, si i est une variableentiere valant 10, lexpression 2 * i + 3 possede le type entier et la valeur 23.

    Dans la partie executable des programmes on trouve deux sortes dexpressions : Lvalue(expressions signifiant

    le contenu de...

    ). Certaines expressions sont representees par une formule

    qui determine un emplacement dans la memoire ; la valeur de lexpression est alors definie comme lecontenude cet emplacement. Cest le cas des noms des variables, des composantes des enregistrements etdes tableaux, etc. Une lvalue possede trois attributs : une adresse, un type et une valeur. Exemples : x,

    table[i], fiche.numero. Rvalue (expressions signifiant la valeur de...

    ). Dautres expressions ne sont pas associees a un empla-

    cement de la memoire : elles ont un type et une valeur, mais pas dadresse. Cest le cas des constantes etdes expressions definies comme le resultat dune operation arithmetique. Une rvaluene possede que deuxattributs : type, valeur. Exemples : 12, 2 * i + 3.

    Toute lvaluepeut etre vue comme une rvalue; il suffit dignorer le contenant (adresse) pour ne voir que lecontenu (type, valeur). La raison principale de la distinction entre lvalue et rvalueest la suivante : seule unelvaluepeut figurer a gauche du signe = dans une affectation ; nimporte quellervaluepeut apparatre a droite.Cela justifie les appellations lvalue ( left value ) etrvalue ( right value ).

    Les sections suivantes preciseront, pour chaque sorte dexpression complexe, sil sagit ou non dune lvalue.Pour les expressions simples, cest-a-dire les constantes litterales et les identificateurs, la situation est la suivante :

    sont des lvalue :

    les noms des variablessimples(nombres et pointeurs), les noms des variables dun type struct ou union

    11Effet de bordest un barbarisme ayant pour origine lexpression anglaise side effect quon peut traduire par effet secondairesouvent un peu cache, parfois dangereux.

    18 c H. Garreta, 1988-2006

  • 5/21/2018 Le Langage C

    19/125

    2 OPERATEURS ET EXPRESSIONS 2.2 Presentation detaillee des operateurs

    ne sont pas des lvalue : les constantes, les noms des variables de type tableau, les noms des fonctions.

    2.1.2 Priorite des operateurs

    C comporte de tres nombreux operateurs. La plupart des caracteres speciaux designent des operations etsubissent les memes regles syntaxiques, notamment pour ce qui concerne le jeu des priorites et la possibilite deparenthesage. La table 2 montre lensemble de tous les operateurs, classes par ordre de priorite.

    prior operateurs sens de lassociativite 15 () [] . -> 14 ! ~ ++ -- -un *un &un sizeof (type) 13 *bin / % 12 + -bin 11 > 10 < >= 9 == !=

    8 &bin 7 ^ 6 | 5 && 4 || 3 ? : 2 = *= /= %= += -= = &= ^= |= 1 ,

    Tab. 2 Operateurs du langage C

    Remarque. Dans certains cas un meme signe, comme -, designe deux operateurs, lun unaire (a un argu-ment), lautre binaire (a deux arguments). Dans le tableau 2, les suffixes un etbinprecisent de quel operateur

    il sagit.

    Le signe indique lassociativite de gauche a droite

    ; par exemple, lexpressionx - y - z signifie (x -

    y ) - z. Le signeindique lassociativite de droite a gauche ; par exemple, lexpression x = y = z signifiex = ( y = z ).

    Notez que le sens de lassociativite des operateurs precise la signification dune expression, mais en aucuncas la chronologiede levaluation des sous-expressions.

    2.2 Presentation detaillee des operateurs

    2.2.1 Appel de fonction()

    Operation : application dune fonction a une liste de valeurs. Format :exp0 ( exp 1 , ... expn )

    exp1 , ... expn sont appeles les arguments effectifs de lappel de la fonction. exp0 doit etre de type fonctionrendant une valeur de type Tou bien12 adresse dune fonction rendant une valeur de type T. Alorsexp0 (exp 1, ...expn )possede le type T. La valeur de cette expression decoule de la definition de la fonction (a linterieurde la fonction, cette valeur est precisee par une ou plusieurs instructions return exp ; ).

    Lexpressionexp0 (exp1 , ... expn ) nest pas une lvalue.

    Exemple :

    y = carre(2 * x) + 3;

    sachant que carre est le nom dune fonction rendant un double, lexpression carre(2 * x)a le type double.Un coup dil au corps de la fonction (cf. section 1.6.2) pourrait nous apprendre que la valeur de cette expressionnest autre que le carre de son argument, soit ici la valeur 4x2.

    12Cette double possibilite est commentee a la section 6.3.4.

    c H. Garreta, 1988-2006 19

  • 5/21/2018 Le Langage C

    20/125

    2.2 Presentation detaillee des operateurs 2 OP ERATEURS ET EXPRESSIONS

    Les contraintes supportees par les arguments effectifs ne sont pas les memes dans le C ANSI et dans le Coriginal (ceci est certainement la plus grande difference entre les deux versions du langage) :

    A. En C ANSI, si la fonction a ete definie ou declaree avec prototype (cf. section 4.1) : le nombre des arguments effectifs doit correspondre a celui des arguments formels13 ; chaque argument effectif doit etre compatible, au sens de laffectation, avec largument formel correspon-

    dant; la valeur de chaque argument effectif subit eventuellement les memes conversions quelle subirait dans

    laffectationargument formel = argument effectif

    B. En C original, ou en C ANSI si la fonction na pas ete definie ou declaree avec prototype : aucune contrainte (de nombre ou de type) nest imposee aux arguments effectifs ; tout argument effectif de type char ou shortest converti en int ; tout argument effectif de type float est converti en double ; les autres arguments effectifs ne subissent aucune conversion.

    Par exemple, avec la fonction carredefinie a la section 1.6.2, lappel

    y = carre(2);

    est errone en C original (la fonction recoit la representation interne de la valeur entiere 2 en croyant que

    cest la representation interne dun double) mais il est correct en C ANSI (lentier 2 est converti en doubleaumoment de lappel).

    Toutes ces questions sont reprises plus en detail a la section 4.

    Remarque 1. Bien noter que les parentheses doivent apparatre, meme lorsque la liste des arguments estvide. Leur absence ne provoque pas derreur, mais change completement le sens de lexpression. Cela constitueun piege assez vicieux tendu aux programmeurs dont la langue maternelle est Pascal.

    Remarque 2. Il faut savoir que lorsquune fonction a ete declaree comme ayant des arguments en nombrevariable (cf. section 4.3.4) les arguments correspondant a la partie variable sont traites comme les argumentsdes fonctions sans prototype, cest-a-dire selon les regles de la sectionB ci-dessus.

    Cette remarque est loin detre marginale car elle concerne, excusez du peu, les deux fonctions les plusutilisees : printfet scanf. Ainsi, quand le compilateur rencontre linstruction

    printf(expr0, expr1, ... exprk);

    il verifie que expr0 est bien de type char *, mais les autres parametres effectifs expr1, ... exprk sont traitesselon les regles de la section B.

    2.2.2 Indexation[]

    Definition restreinte(element dun tableau). Operation : acces au ieme element dun tableau. Format :

    exp0 [ exp 1 ]

    exp0 doit etre de type tableau dobjets de typeT , exp 1 doit etre dun type entier. Alors exp 0[exp1] est detypeT; cette expression designe lelement du tableau dont lindice est donne par la valeur de exp 1.

    Deux details auxquels on tient beaucoup en C : le premier element dun tableau a toujours lindice 0 ; il nest jamais verifie que la valeur de lindice dans une reference a un tableau appartient a lintervalle

    0...N 1 determine par le nombre Ndelements alloues par la declaration du tableau. Autrement dit, ilny a jamais de

    test de debordement

    .

    Exemple. Lexpression t[0]designe le premier element du tableau t, t[1] le second, etc.

    En C, les tableaux sont toujours a un seul indice ; mais leurs composantes peuvent etre a leur tour destableaux. Par exemple, un element dune matrice rectangulaire sera note :

    m[i][j]

    Une telle expression suppose que m[i] est de type tableau dobjets de type T et donc que m est de type

    tableau de tableaux dobjets de type T

    . Cest le cas, par exemple, sima ete declaree par une expression dela forme (NLet NCsont des constantes) :

    double m[NL][NC];

    13Il existe neanmoins un moyen pour ecrire des fonctions avec un nombre variable darguments (cf. section 4.3.4)

    20 c H. Garreta, 1988-2006

  • 5/21/2018 Le Langage C

    21/125

    2 OPERATEURS ET EXPRESSIONS 2.2 Presentation detaillee des operateurs

    Definition complete (indexation au sens large). Operation : acces a un objet dont ladresse est donneepar une adresse de base et un deplacement. Format :

    exp0 [ exp 1 ]

    exp0 doit etre de type adresse dun objet de typeT ,exp1 doit etre de type entier. Alors exp0[exp1]designelobjet de type Tayant pour adresse (voir la figure 2) :

    valeur(exp0) + valeur(exp1)

    taille(T)

    exp0

    exp1

    Fig.2 Lindexation

    Il est clair que, siexp0 est de type tableau, les deux definitions de lindexation donnees concident. Exemple :si t est un tableau dentiers et p un

    pointeur vers entier

    auquel on a affecte ladresse de t[0], alors les

    expressions suivantes designent le meme objet :

    t[i] p[i] *(p + i) *(t + i)

    Dans un cas comme dans lautre, lexpression exp 0[exp1]est une lvalue, sauf si elle est de type tableau.

    2.2.3 Selection .

    Operation : acces a un champ dune structure ou dune union. Format :

    exp . identif

    exp doit posseder un type struct ou union, et identif doit etre le nom dun des champs de la structure ou delunion en question. En outre, exp doit etre une lvalue. Alors, exp.identif designe le champ identif de lobjetdesigne parexp.

    Cette expression est unelvalue, sauf si elle est de type tableau.

    Exemple. Avec la declaration

    struct personne {

    long int num;

    struct {

    char rue[32];

    char *ville;

    } adresse;

    } fiche;

    les expressionsfiche.num fiche.adresse fiche.adresse.rue

    etc.designent les divers champs de la variable fiche. Seules les deux premieres sont des lvalue.

    2.2.4 Selection dans un ob jet pointe->

    Operation : acces au champ dune structure ou dune union pointee. Format :

    exp->identif

    exp doit posseder le type adresse dune structure ou dune union

    etidentif doit etre le nom dun des champs

    de la structure ou de lunion en question. Dans ces conditions, exp->identif designe le champ identif de lastructure ou de lunion dont ladresse est indiquee par la valeur de exp.

    Cette expression est unelvalue, sauf si elle est de type tableau.Ainsi,exp ->identifest strictement synonyme de (*exp).identif (remarquez que les parentheses sont indis-

    pensables).

    Par exemple, avec la declaration :

    c H. Garreta, 1988-2006 21

  • 5/21/2018 Le Langage C

    22/125

    2.2 Presentation detaillee des operateurs 2 OP ERATEURS ET EXPRESSIONS

    struct noeud {

    int info;

    struct noeud *fils, *frere;

    } *ptr;

    les expressions suivantes sont correctes :

    ptr->info ptr->fils->frere ptr->fils->frere->frere

    2.2.5 Negation !

    Operation : negation logique. Format :!exp

    Aucune contrainte. Cette expression designe une valeur de lensemble{0, 1}, definie par :

    !exp

    1, si exp = 00, si exp = 0

    Cette expression nest pas une lvalue.Remarque. Bien que cela ne soit pas exige par le langage C, on evitera de nier (et plus generalement

    de comparer a zero) des expressions dun type flottant (float,double). A cause de limprecision inherente a laplupart des calculs avec de tels nombres, legalite a zero dun flottant nest souvent que le fruit du hasard.

    2.2.6 Complement a 1 ~

    Operation : negation bit a bit. Format :~exp

    exp doit etre dun type entier. Cette expression designe lobjet de meme type que exp qui a pour codage interne

    la configuration de bits obtenue en inversant chaque bit du codage interne de la valeur de exp : 1 devient 0, 0devient 1.

    Cette expression nest pas une lvalue.

    Remarque. Le complement a un nest pas une operation abstraite (cf. section 2.3.3). La portabilite dunprogramme ou cet operateur figure nest donc pas assuree.

    2.2.7 Les celebres ++ et --

    Il existe deux operateurs unaires ++ differents : lun est postfixe (ecrit derriere loperande), lautre prefixe(ecrit devant).

    1. Operation : post-incrementation. Format :exp++

    exp doit etre de type numerique (entier ou flottant) ou pointeur. Ce doit etre une lvalue. Cette expression estcaracterisee par :

    un type : celui de exp ; une valeur : la meme que exp avant levaluation de exp ++ ; un effet de bord : le meme que celui de laffectationexp = exp + 1.

    2. Operation : pre-incrementation. Format :++exp

    exp doit etre de type numerique (entier ou flottant) ou pointeur. Ce doit etre une lvalue. Cette expression estcaracterisee par :

    un type : celui de exp ; une valeur : la meme que exp apres levaluation de exp++ ; un effet de bord : le meme que celui de laffectationexp = exp + 1.

    Les expressions exp ++et ++exp ne sont pas des lvalue.

    22 c H. Garreta, 1988-2006

  • 5/21/2018 Le Langage C

    23/125

    2 OPERATEURS ET EXPRESSIONS 2.2 Presentation detaillee des operateurs

    Exemple.Laffectation equivaut a

    y = x++ ; y = x ; x = x + 1 ;

    y = ++x ; x = x + 1 ; y = x ;

    Loperateur ++ beneficie de larithmetique des adresses au meme titre que +. Ainsi, si exp est de type pointeur vers un objet de type T , la quantite effectivement ajoutee aexp par lexpression exp ++depend de

    la taille deT.Il existe de meme deux operateurs unaires -- donnant lieu a des expressions exp-- et --exp. Lexplication

    est la meme, en remplacant +1 par1.Application : realisation dune pile. Il est tres agreable de constater que les operateurs ++ et -- et la

    maniere dindexer les tableaux en C se combinent harmonieusement et permettent par exemple la realisationsimple et efficace de piles par des tableaux, selon le schema suivant :

    declaration et initialisation dune pile (OBJET est un type predefini, dependant du probleme particulierconsidere ; MAXPILE est une constante representant un majorant du nombre delements dans la pile) :

    OBJET espace[MAXPILE];

    int nombreElements = 0;

    operation

    empiler la valeur dex

    :if (nombreElements >= MAXPILE)

    erreur("tentative dempilement dans une pile pleine");

    espace[nombreElements++] = x;

    operation depiler une valeur et la ranger dans x

    :

    if (nombreElements

  • 5/21/2018 Le Langage C

    24/125

    2.2 Presentation detaillee des operateurs 2 OP ERATEURS ET EXPRESSIONS

    2.2.10 Obtention de ladresse &

    Operation : obtention de ladresse dun objet occupant un emplacement de la memoire. Format :&exp

    exp doit etre une expression dun type quelconque T. Ce doit etre une lvalue.

    Lexpression&exp a pour type adresse dun objet de typeT et pour valeur ladresse de lob jet represente

    parexp. Lexpression &exp nest pas une lvalue.

    Ainsi, si i est une variable de type int et p une variable de type pointeur vers un int , alors a la suitede linstruction

    p = &i;

    i et *p designent le meme objet.

    Exemple 1. Une utilisation frequente de cet operateur est lobtention de ladresse dune variable en vue dela passer a une fonction pour quelle modifie la variable :

    scanf("%d%lf%s", &i, &t[j], &p->nom);

    Exemple 2. Une autre utilisation elegante de cet operateur est la creation de composantes fixes dansles structures chanees. Le programme suivant declare une liste chanee circulaire representee par le pointeur

    entreeet reduite pour commencer a un unique maillon qui est son propre successeur (voir figure 3) ; dautresmaillons seront crees dynamiquement durant lexecution :

    entree

    en_tete_fixe

    Fig.3 Maillon fixe en tete dune liste chanee

    struct en_tete {long taille;

    struct en_tete *suivant;

    } en_tete_fixe = { 0, &en_tete_fixe };

    struct en_tete *entree = &en_tete_fixe;

    Remarque. Une expression reduite a un nom de tableau, a un nom de fonction ou a une constante chanede caracteres est consideree comme une constante de type adresse ; loperateur & applique a de telles expressionsest donc sans objet. Un tel emploi de & devrait etre considere comme errone, mais beaucoup de compilateurs secontentent de lignorer.

    2.2.11 Operateursizeof

    Operation : calcul de la taille correspondant a un type. Premiere forme :

    sizeof ( descripteur-de-type )

    Cette expression represente un nombre entier qui exprime la taille quoccuperait en memoire un objet possedantle type indique (les des