cours langage c

Upload: yuri-cn-blue

Post on 30-Oct-2015

55 views

Category:

Documents


1 download

TRANSCRIPT

  • Langage C - Jacoboni - 16/02/98 -1

    Cours Langage C - Pierre Jacoboni 16 fvrier 1998

    Avertissement :Ce polycopi sur le Langage C ne constitue qu'un support de cours de langage deprogrammation. Il est incomplet et ncessite de nombreux complments donns en coursmagistral. C'est la raison pour laquelle il est donn aux tudiants sous une forme plusare, permettant la prise de notes. Il s'adresse des tudiants de Deup.Certains concepts sont volontairement absents de ce texte, comme la compilationspare, etc... Ces concepts sont dvelopps en TD/TP en cours d'anne.

    Sommaire : Premire partie . : Introduction - De lApplicatif lImpratif Deuxime partie : Types fondamentaux du C Troisime partie : Expressions & Oprateurs Quatrime partie : Les Principales instructions Cinquime Partie: La Programmation en C Sixime partie.... : Les Pointeurs et les Tableaux Septime partie : Structures et Unions Huitime partie . : Entres / sorties Neuvime partie : Complments 1 : Le prprocesseur

    ..........................: Complments 2 : Arguments de la ligne de commande Dixime partie... : Les Types de Donnes Abstraits Onzime partie . : Sujets de TD et solutions Douzime partie : Sujets de TP

  • Langage C - Jacoboni - 16/02/98 -2

    1. PREMIRE PARTIE : INTRODUCTION - DE LAPPLICATIF LIMPRATIF 6

    1.1. LES LANGAGES DE PROGRAMMATION . 61.1.1. LES LANGAGES FONCTIONNELS 61.1.2. LES LANGAGES IMPRATIFS 61.1.3. LES DIFFRENCES ENTRE LANGAGES IMPRATIFS ET APPLICATIFS 61.2. LANGAGE C 71.2.1. HISTORIQUE 71.2.2. PROGRAMME N1 81.2.3. UN EXEMPLE DE PROGRAMMATION FONCTIONNELLE EN C 91.2.4. PROGRAMME N2 91.2.5. LES BOUCLES : PROGRAMME N3 101.2.6. AFFICHAGE SUR L'CRAN 101.2.7. LECTURE AU CLAVIER 101.2.8. LES TABLEAUX : PROGRAMME N4 111.2.9. LES BOOLENS : PROGRAMME N5 111.2.10. TABLEAUX DEUX DIMENSIONS : PROGRAMME N6 131.2.11. AFFECTATION 131.2.12. LES STRUCTURES : PROGRAMME N7 131.2.13. STRUCTURE GNRALE D'UN PROGRAMME EN C - ORDRE DES DCLARATIONS 141.2.14. UNE CARACTRISTIQUE DU C : LES CARACTRES 141.2.15. EXEMPLE TYPIQUE DE TRAITEMENT DE CARACTRES EN C 15

    2. DEUXIME PARTIE : TYPES FONDAMENTAUX DU C 16

    2.1. LES ENTIERS 162.1.1. LES CARACTRES 162.1.2. LES AUTRES ENTIERS 162.2. LES RELS 172.3. LES CONSTANTES 172.3.1. CONSTANTES DE TYPE CHAR 172.3.2. CONSTANTES DE TYPE ENTIRES 172.3.3. CONSTANTES DE TYPE LOGIQUE 182.3.4. CONSTANTES DE TYPE REL 182.3.5. CONSTANTES CHAINE DE CARACTRES 18

    3. TROISIME PARTIE : EXPRESSIONS & OPRATEURS 19

    3.1. EXPRESSIONS ET OPRATEURS 193.1.1. LES OPRATEURS ARITHMTIQUES 193.1.2. LES OPRATEURS RELATIONNELS 193.1.3. LES OPRATEURS LOGIQUES 193.1.4. PRIORITS DES OPRATEURS 203.1.5. PRIORIT DES OPRATEURS : EXEMPLES 203.2. AUTRES OPRATEURS 213.2.1. OPRATEURS BINAIRES 213.2.2. OPRATEUR D'AFFECTATION 213.2.3. OPRATEUR CONDITIONNEL ET OPRATEUR DE SQUENCE 223.2.4. OPRATEUR D'APPEL DE FONCTIONS () 223.2.5. OPRATEUR SIZEOF 223.2.6. OPRATEUR DE CAST (T) A 223.3. CONVERSIONS NUMRIQUES 22

  • Langage C - Jacoboni - 16/02/98 -3

    3.4. CONVERSIONS IMPLICITES 22

    4. QUATRIME PARTIE : LES PRINCIPALES INSTRUCTIONS 24

    4.1. IF 244.2. IF ... ELSE 244.3. WHILE 244.4. FOR 244.5. DO ... WHILE 244.6. BREAK 254.7. CONTINUE 254.8. RETURN; 254.9. RETURN EXPRESSION; 254.10. GOTO TIQUETTE ; 254.11. SWITCH 25

    5. CINQUIME PARTIE : LA PROGRAMMATION EN C 26

    5.1. LES FONCTIONS 265.1.1. PRSENTATION GNRALE 265.1.2. DFINITION DE FONCTION 265.1.3. DCLARATION DE FONCTION 265.1.4. UN PROGRAMME COMPLET EN C 275.1.5. RCURSIVIT 275.2. STRUCTURE DES PROGRAMMES 285.2.1. CLASSE DE MMORISATION 285.2.2. VARIABLES DE CLASSE AUTOMATIQUE 285.2.3. VARIABLES DE CLASSE EXTERNE 285.2.4. VARIABLES DE CLASSE STATIQUE DES PROGRAMMES MONOFICHIERS 295.3. COMMUNICATION ENTRE MODULES 305.3.1. RGLES DE COMMUNICATION 305.4. UTILISATION DE MAKE 315.4.1. LA SYNTAXE DU MAKEFILE 31

    6. SIXIME PARTIE : LES POINTEURS ET LES TABLEAUX 33

    6.1. POINTEURS ET ADRESSES 336.2. OPRATIONS SUR LES POINTEURS 336.3. COMPARAISON DE POINTEURS 346.4. SOUSTRACTION DE POINTEURS 346.5. AFFECTATION DE CHANES DE CARACTRES 356.6. POINTEURS ET TABLEAUX 356.7. PASSAGE DES PARAMTRES 366.8. POINTEURS ET TABLEAUX MULTIDIMENSIONNELS 386.9. REPRISE DES PREMIERS EXERCICES DE TD. 406.10. TABLEAUX DE POINTEURS 406.11. POINTEURS DE FONCTIONS 416.12. ALLOCATION DYNAMIQUE 41

    7. SEPTIME PARTIE : STRUCTURES ET UNIONS 43

    7.1. DCLARATION DE STRUCTURE 437.2. INITIALISATION DE STRUCTURE 43

  • Langage C - Jacoboni - 16/02/98 -4

    7.3. ACCS UN CHAMP 437.4. UTILISATION DES STRUCTURES 437.5. TABLEAUX DE STRUCTURES 447.6. STRUCTURES ET POINTEURS 447.7. PASSAGE DE STRUCTURES COMME ARGUMENTS DE FONCTIONS 447.8. STRUCTURES RCURSIVES 457.9. LES UNIONS 457.10. SCHMAS D'IMPLANTATION 46

    8. HUITIME PARTIE : ENTRES / SORTIES 47

    8.1. LES E/S FORMATES : PRINTF 478.2. LES E/S FORMATES : SCANF 488.3. LES E/S : LES FICHIERS 488.4. E/S FICHIERS :LES FONCTIONS DE NIVEAUX 1 488.5. E/S FICHIERS :LES FONCTIONS DE NIVEAUX 2 498.6. LES E/S FORMATES 49

    9. NEUVIME PARTIE : COMPLMENTS 51

    9.1. COMPLMENTS 1 : LE PRPROCESSEUR 519.1.1. PREMIRE UTILISATION : SUBSTITUTION DE SYMBOLES 519.1.2. DEUXIME UTILISATION : MACRO-INSTRUCTIONS 519.1.3. TROISIME UTILISATION : INCLUSION DE FICHIER 529.1.4. QUATRIME UTILISATION : COMPILATION CONDITIONNELLE 529.1.5. LE PRPROCESSEUR : OPRATEUR # 539.1.6. LE PRPROCESSEUR : OPRATEUR ## 539.1.7. EXEMPLE DE FICHIER HEADER : DEF.H 539.2. COMPLMENTS 2 : ARGUMENTS DE LA LIGNE DE COMMANDE 54

    10. DIXIME PARTIE : TYPES DE DONNES ABSTRAITS 55

    10.1. LES TYPES DE DONNES ABSTRAITS 5510.1.1. DFINITION 1 : 5510.1.2. DFINITION 2 : 5510.1.3. DFINITION 3 : INCARNATION D'UN TDA 5510.1.4. AVANTAGES DES TDA 5510.1.5. INCONVNIENTS DES TDA 5510.2. LE TDA L ISTE 5610.2.1. DFINITIONS : 5610.2.2. HYPOTHSES 5610.2.3. SIGNATURE DU TDA LISTE 5610.2.4. OPRATIONS CLASSIQUES SUR LES LISTES 5710.2.5. LISTEPRECEDENT 5710.2.6. LISTELOCALISER 5810.2.7. ALGORITHMES ABSTRAITS SUR LE TDA LISTE 5810.3. RALISATIONS DU TDA LISTE 5910.3.1. MISE EN UVRE DES LISTES PAR CELLULES CONTIGUS 5910.3.2. MISE EN UVRE DES LISTES PAR CELLULES CHANES 6010.3.3. LISTES SIMPLEMENT CHANES SANS EN-TTE 6110.3.4. LISTES SIMPLEMENT CHANES AVEC EN-TTE 6110.3.5. LISTES SIMPLEMENT CHANES CIRCULAIRES 6210.3.6. LISTES DOUBLEMENT CHANES 6210.3.7. MISE EN UVRE DES LISTES PAR CURSEURS (FAUX-POINTEURS) 62

  • Langage C - Jacoboni - 16/02/98 -5

    10.4. COMPARAISON DES RALISATIONS 6310.5. CONCLUSION 6410.6. L ISTING DE LA RALISATION DU TDA L ISTE PAR CELLULES CONTIGES 6410.7. L ISTING DE LA RALISATION DU TDA L ISTE PAR CELLULE CHANE SANS ENTTE . 69

    11. ONZIME PARTIE - SUJETS DE TD ET SOLUTIONS 70

    12. DOUZIME PARTIE : SUJETS DE TP 87

  • Langage C - Jacoboni - 16/02/98 -6

    1. Premire partie : Introduction - De lApplicatif lImpratif

    1.1. Les langages de programmation.

    1.1.1. Les langages fonctionnels Un langage fonctionnel ou applicatif, est un langage bas sur lapplication de

    fonction au sens des fonctions mathmatiques. Une dfinition de fonction comme f(x)=10*x donne une rgle qui montre

    comment chaque lment du domaine de la fonction f peut tre mis encorrespondance avec un lment du codomaine de la fonction.

    1.1.2. Les langages Impratifs Un programme crit dans un langage impratif (procdural) provoque son effet

    par le changement de la valeur de variables au moyen dinstructions

    La conception des langages impratifs t troitement lie la conceptiondes ordinateurs traditionnels qui repose sur larchitecture de Von Neumann (La mmoire possde des emplacements adressables de faon individuelle)

    Quest-ce quune variable ? on peut voir la variable des langages deprogrammation impratifs comme une abstraction de lemplacement en

    Lexcution dun programme dans un langage impratif seffectue en excutantsquentiellement des instructions. Les instructions conditionnelles et itrativesservant modifier lordre dexcution des instructions.

    1.1.3. Les Diffrences entre langages Impratifs et Applicatifs La plus importante diffrence provient du concept daffectation : il est constitutif

    des langages impratifs alors quil nexiste pas dans un langage purementfonctionnel.

    Lapplication dune fonction a pour effet de renvoyer une nouvelle valeur , alorsque laffectation provoque une modification de la valeur dun objet existant.

    Le problme de laffectation est que, quand elle est utilise dans des sous-programmes avec des paramtres passs par rfrence ou avec des variablesnon locales, elle peut induire des effets secondaires ou effets de bords.

    Exemple : Soit la fonction Ada suivante :function bizarre return integer isbegin

    Var_Glob = Var_Glob + 1 ;return Var_Glob ;

    end bizarre ;Des appels diffrents de bizarre renvoient des rsultats diffrents, ainsilexpression relationnelle bizarre = bizarre est fausse ! ! !

    Avec de tels effets secondaires, il devient difficile de raisonner sur lesprogrammes pour prouver quils sont corrects.

    En excluant laffectation, il est possible de sassurer que les fonctions neprovoquent pas deffet secondaire et quelles se comportent comme des

    Lordre prcis dans lequel les fonctions sont appeles na alors pas ; appeler une fonction avec un certain paramtre donnera

  • Langage C - Jacoboni - 16/02/98 -7

    Cest ce quon appelle la transparence rfrentielle et cest ce qui permetdvaluer diffrentes expressions simultanmnt sur un systmemultiprocesseur.

    En revanche il est trs difficile de dterminer quelles parties dun programmeimpratif peuvent tre excutes simultanment, cela cause des intractionsqui ont lieu par lintermdiaire demplacement mmoire partags entre lesdiffrentes parties dun tel programme.

    Les langages fonctionnels noncent le quoi (ce qui doit tre fait) plutt que comment (comment ce doit tre fait). Ils se situent un niveau plus lev

    1.2. Langage C

    1.2.1. Historique Naissance : 1970 Pre : Dennis RITCHIE (Bell AT&T) sur PDP 11 Objectif : Rcriture d'UNIX (Ken THOMPSON) crit jusqu'alors en

    assembleur et langage B (langage non typ). Consquences : Le succs d'Unix, notamment dans les

    universits amricaine a fortement contribu la popularit du langage C.

    Aujourd'hui C est le langage de programmation sous UNIX

    Rputation : C est un langage d'assemblage portable de hautniveau.

    Attention : Ce qui prcde dpend du programmeur et du typed'application que l'on ralise avec C.

    Conclusion : C est un langage volu permissif, capable de traiterde manire standard des informations de bas niveau trsproches de la structure matrielle des ordinateurs (mots,adresses, registres, octets, bits ...)

    Dfinition du langage C : Kernighan & Ritchie : le langage C - 1978 Norme Ansi - 1982

    Bibliographie : Le langage C norme Ansi (2me dition)Kernighan &

    Ritchie (masson) Langage C norme ansi

    objet" Drix(masson) Programmation en C Gottfried (Schaum) Le Langage C++ (2ime dition)Stroustrup (Addison

    Wesley)

  • Langage C - Jacoboni - 16/02/98 -8

    1.2.2. Programme N1/* Premier Programme en C */

    void main (){ printf ("Bonjour!\n");}

    En C, que des fonctions. L'diteur de lien attend que l'une des fonctions s'appelle main Le C est case sensitive donc Main() et PrintF(..) sont incorrects Les accolades { et } sont les dlimiteurs de blocs Le ; est le terminateur d'instruction simple. La fonction printf n'est pas une fonction prdfinie, elle fait partie de la

    bibliothque standard. L'argument de printf est une chaine de caractres dlimite par des ",

    et est transmise telle quelle au priphrique de sortie (par dfaut

    Cet argument constitue le format d'affichage, et peut contenir entreautre des controles comme \n : newline, \t : tabulation, \b : backspace.

    En C, il faut grer soi-mme ses changements de lignes.printf("Bonjour");printf("tout le monde");

    donnera : Bonjourtout le monde comme rsultat.printf("Bonjour\n");printf("tout le monde");

    est quivalent printf("Bonjour");printf("\ntout le monde");

    mais aussi : printf("Bonjour\ntout le monde");le rsultat tant :

    Bonjourtout le monde.

  • Langage C - Jacoboni - 16/02/98 -9

    1.2.3. Un exemple de programmation fonctionnelle en Cint max (int a, int b){

    if (a > b)return a ;

    else return b ;}int min (int a, int b){

    if (a < b)return a ;

    else return b ;}int difference (int a, int b, int c){

    return (max (a, max(b,c)) - min (a, min (b, c))) ;}int main (){ printf ("%d", difference (10, 4, 7)) ; }

    1.2.4. Programme N2

    /* Second Programme en C : Calcul de l'epsilon machine */

    void main (){ float eps; float min=0.0, max=1.0; const int N=30; int i=0; while (i 1.0)

    /* eps est trop grand */max=eps;

    else/* eps est trop petit */min=eps;

    i=i+1; } printf ("On a trouv %g comme valeur finale\n",eps);}

    Ligne 2 : { est place avant les dclarations Ligne 3 : Les variables sont dclares par le nom du type suivi par les

    noms de variables. Il n'y a pas d'ordre impos pour les dclarations. Lignes 4&6 : Les variables peuvent tre initialises au moment de leur

    Ligne 7 : La condition d'un while est entre () Ligne 8 : L'affectation est =

  • Langage C - Jacoboni - 16/02/98 -10

    Ligne 9 : Conditionnelle :if (exp_logique) instruction else instruction

    instruction pouvant tre une instruction simple (termine par un;) ou un bloc d'instructions simples ({}).

    comme pour le while l'expression doit tre parenthse. Ligne 10&13 : Commentaire plac entre /* et */ Ligne 15 : Oprateurs d'incrmentation possibles ++i (ou i++).

    1.2.5. Les boucles : Programme N3 On pourrait rcrire la boucle avec un for, ce qui donnerait :

    en Cfor (i=0 ; i1.0 max=eps ; else min=eps;}

    Le bouclage for en C se dcompose en trois parties : i=0 : initialisation du contrle i < N : condition de bouclage i++ : instruction excuter avant le rebouclage.

    1.2.6. Affichage sur l'cran Forme gnrale de printf

    printf("....format....", e1, e2, ....); Le premier argument est obligatoirement une chane de caractres

    constitue de caractres imprimables, de contrles (\), et de codesformats (%)

    Exemples de codes formats %d, %o, %x pour les entiers %f, %e, %g pour les rels

    1.2.7. Lecture au clavier Lecture par appel de la fonction de la bibliothque standard, scanf qui

    fonctionne de faon analogue printf.scanf("format",&v1,&v2,...);

    le format tant constitu ici uniquement de codes formats. Pour lire unentier on utilisera par exemple le code format %d.

    le & signifie que la variable v1 doit tre passe par adresse et non parvaleur.

  • Langage C - Jacoboni - 16/02/98 -11

    1.2.8. Les Tableaux : Programme N4

    /* Quatrime programme en C : tableau */

    void main(){ const int N=10; int t[N],i; for (i=0;i

  • Langage C - Jacoboni - 16/02/98 -12

    pour rechercher une information. Version grosBta*/

    void main(){ const int N=10; int t[N], i, x; typedef enum BOOL {false , true} bool; bool fini=false, present=false; for (i=0;i

  • Langage C - Jacoboni - 16/02/98 -13

    1.2.10. Tableaux deux dimensions : Programme N6

    /* Sixime programme C : tableaux deuxdimensions */

    void main(){const int N=4; float mat1[N][N], mat2[N][N], mat3[N][N], som; float m[][] = {{1., 0., 0., 0.} {1., 1., 0., 0.} {0., 2., 1., 0.} {0., 0., 3., 1.}}; int i,j,k; for (i=0; i< N; i++) for (j=0;j

  • Langage C - Jacoboni - 16/02/98 -14

    En C on manipule les membres ou champs de la structure avec le .

    /* Septime programme C :les structures */

    typedef struct COMPLEXE { float re; float im; } complexe;

    complexe add(complexe z1, complexe z2){ complexe z; z.re = z1.re + z2.re; z.im = z1.im + z2.im; return z;}

    void main(){ complexe u,v,w; float a,b,c,d; printf("Entrez 4 valeurs relles\n"); scanf("%g%g%g%g",,a,b,c,d); u.re=a ; u.im=b; v.re=c ; v.im=d; w=add(u,v); printf("Somme=(%g,%g)\n",w.re,w.im);}

    1.2.13. Structure Gnrale d'un programme en C - Ordre des dclarations Il n'existe pas d'ordre impratif de dclaration des divers lments d'un

    programme en C. Les fonctions ne peuvent pas tre emboites, tout est au mme niveau. Quand le compilateur rencontre un appel de fonction qui n'a pas t

    dfinie avant, il fait l'hypothse qu'elle renvoie un entier. Si c'est bien le cas, pas de problme, sinon a ne marche pas. Pour viter toute surprise dsagrable, il est ncessaire de prototyper

    les fonctions. Le prototype n'est pas une dfinition, c'est une indicationpour le compilateur quant aux types des paramtres de la fonction et

    Ca marche Ca ne marche pasvoid main(){ int a,b,c; a=add (b,c); printf("%d",a);}int add(int x1,int x2){return x1+x2;}

    void main(){ float a,b,c; a=add (b,c); printf("%f",a);}float add(float x1, float x2){return x1+x2;}

    void main(){ float a,b,c; float add(float,float); a=add (b,c); printf("%f",a);}float add(float x1, float x2){return x1+x2;}

    =>Prototype de add

    1.2.14. Une caractristique du C : les caractres

  • Langage C - Jacoboni - 16/02/98 -15

    La notion de caractre n'est pas conceptualise en C. Un caractre enC est comme un caractre au niveau de la machine, c'est dire unnombre entier. (son code ASCII)

    Le type char et le type int sont donc trs voisins, l'unique diffrencetient au fait que le char est gnralement cod sur 1 octet tandis quel'int l'est sur 2.

    Les littraux caractres comme 'a', '8', '?' sont des int en C. On peut donc crire 'a'+2 qui est la somme de deux int et qui donne un

    On peut galement ajouter un int et un char,int x,i ; char c;x= i+c /* c est automatiquement converti en int */

    1.2.15. Exemple Typique de traitement de caractres en C Exemple de programme C recopiant l'entre sur la sortie

    #include void main(){ int c;

    c=getchar()while (c != EOF) {

    putchar(c) ;c=getchar() ;}}

    EOF est une pseudo-constante dfinie par un #define dans stdio.h etvaut gnralement -1.

    La fonction getchar renvoie un entier pris sur l'entre standard (codeascii du caractre) et -1 si la fin de fichier est atteinte. La fonctionputchar prend un entier en paramtre effectif et envoie le caractrecorrespondant sur la sortie standard.

    Ce programme est syntaxiquement correct, mais ne sera jamaisrellement crit comme cela (sauf par un dbutant). On crira plutt :

    #include void main(){ int c;

    while ((c = getchar() ) != EOF) {putchar(c);}}

    En C une expression syntaxiquement valide renvoie un rsultat, c'est lecas de l'affectation qui renvoie comme valeur la valeur affecte. donc

    (( c = getchar () ) != EOF ) se dcompose enc = getchar(), la valeur de cette expression est ensuite

    compare EOF.

  • Langage C - Jacoboni - 16/02/98 -16

    2. Deuxime partie : Types fondamentaux du C En C il n'y a que 2 types fondamentaux, les entiers et les rels. Pour les entiers : 4 variantes :

    Les caractres char Les entiers courts short int Les entiers longs long int Les entiers classiques int

    Ces quatre variantes peuvent tre signes ou non. (unsigned), ce qui donne au total8 types pour les entiers.

    Pour les rels : 3 variantes : Les rels simple prcision float Les rels double prcision double Les rels quadruple prcision long double;

    2.1. Les entiers

    2.1.1. Les caractres En C un caractre est un entier car il s'identifie son code ASCII (le

    plus souvent). Un caractre peut donc tre cod sur un octet. On peut donc appliquer toutes les oprations entires sur les

    caractres (addition, soustraction ...). Problme, On ne sait pas si ce sont des entiers signs ou non, car cela

    dpend des machines. Les autres variantes du type entiers sonttoujours signes par dfaut (pas de unsigned).

    C'est pourquoi oncrit

    pltot que

    int c;if

    ((c=getchar())!=EOF)....

    char c;if ((c=getchar())!=EOF)...

    car getchar () peut renvoyer -1 (et donc ce test ne fonctionnera quesur les machines ou les caractres sont signs).

    2.1.2. Les autres entiers Un entier correspond gnralement un mot machine. Les attributs short, long, unsigned peuvent qualifier un entier

    long int x; /* x est un entier long (>= 32 bits) */ short int x; /* x est un entier court */ unsigned int x; /* x est un entier non sign */ unsigned short int x; /* x est un entier court non sign */

    Il n'y a pas de taille fixe par le langage, mais le C garanti que1=T_C

  • Langage C - Jacoboni - 16/02/98 -17

    unsigned short x;/* x est un entier court non sign */

    2.2. Les rels Les float sont des rels cods de manire interne sous forme de mantisse/exposant. Les double sont des float plus longs et les long double sont des doubles plus longs. Plus la taille est grande, plus la mantisse est grande et plus la prcision est grande. Comme pour les entiers ces tailles sont dpendantes de la machine, le C garanti

    juste queT_F

  • Langage C - Jacoboni - 16/02/98 -18

    Une constante numrique en base 8 ou 16 est normalement un int. Sile nombre est trop grand le compilateur essaiera dans l'ordre les typesunsigned int, long int, unsigned long int.

    Les constantes de type short int et unsigned short int n'existent pas.

    2.3.3. Constantes de type logique Les constantes de type logique n'existent pas en tant que telle en C.

    On utilise la convention suivante sur les entiers :0 faux et tout entier positif vrai

    2.3.4. Constantes de type rel Les constantes double sont de la forme

    . On peut omettre

    soit : .475e-12soit : 482.

    mais pas les deux On peut omettre

    soit . : 12e7soit : 12.489

    mais pas les deux. Les constantes long double sont des constantes double suivies de l ou

    L Les constantes float sont des constantes double suivie de f ou F

    2.3.5. Constantes chaine de caractres Elles sont constitues de caractres quelconques encadrs par des

    guillemets. ex : "abc". Elles sont stockes en mmoire statique sous la forme d'un tableau de

    caractres termin par la valeur '\0' (valeur entire 0).a b c \0

  • Langage C - Jacoboni - 16/02/98 -19

    3. Troisime Partie : Expressions & Oprateurs

    3.1. Expressions et oprateurs Une expression est une notation de valeur. L'valuation d'une expression est le

    processus par lequel le programme obtient la valeur dsigne. Une expression est constitue d'oprandes et d'oprateurs. Les oprandes dnotent

    les valeurs composer. Ce sont des constantes (littraux), des variables ou desexpressions. Les valeurs sont essentiellement entires ou flottantes; les oprateurssont alors associs des oprations numriques

    Dans le cas de types inadapts, on peut convertir des valeurs d'un type en un autreselon une certaine hirarchie :

    en C un type est surtout une taille mmoire. Il est vident qu'on ne peutconvertir un objet d'une taille X et un objet d'une taille Y si X > Y...

    Le C dfinie la hirarchie des tailles entre les types de la faon suivante :char < int < float < double

    3.1.1. Les oprateurs arithmtiques Les principaux oprateurs arithmtiques sont :

    + Addition - Soustraction * Multiplication / Division entire et relle % Reste de la division entire (Modulo)

    Ces oprateurs (sauf le %) sont applicables aussi bien des entiers

    Dans le cas de 2 oprandes entiers, le rsultat de la division est entier,dans tous les autres cas, il est rel.

    Dans le cas de la division entire,le C garantit que (si b 0) on a :(a/b)*b + a%b = a

    En C, on dispose aussi du - unaire

    3.1.2. Les oprateurs relationnels Les principaux oprateurs relationnels sont :

    ==galit ( de l'affectation) != diffrence > suprieur >= Suprieur ou gal < Infrieur

  • Langage C - Jacoboni - 16/02/98 -20

    || OU de 2 valeurs logiques Ces oprateurs interviennent sur des valeurs de type int : la valeur 0

    est considre comme la valeur FAUX; toutes les autres valeurscomme la valeur VRAI.

    Les valeurs produites sont 0 (FAUX) ou 1 (VRAI) du type int. Les oprateurs && et || impliquent l'valuation de l'oprande gauche

    avant celle de droite. L'oprande de droite peut ne pas tre valu si la valeur obtenue

    partir de l'oprande de gauche suffit dterminer le rsultat : 0 pour l'oprande gauche de l'oprateur && implique FAUX 1 pour l'oprande gauche de l'oprateur || implique VRAI

    int Tab[10];Soit le test : (k < 10) && (Tab[k] != v)

    Si k est suprieur ou gal 10 ,l'expression (Tab[k] != v) ne sera pasvalue et il vaut mieux car pour k suprieur ou gal 10 Tab[k] est

    3.1.4. Priorits des oprateurs Lors de l'valuation des expressions, certaines rgles sont appliques

    systmatiquement par le compilateur. Le programmeur doit donc entenir compte lors de l'criture d'un programme.

    Les oprateurs les plus prioritaires sont appliqus en premier Les oprateurs de mme priorit sont appliqus de la gauche

    vers la droite (sauf les oprateurs unaires qui sont appliqus dela droite vers la gauche)

    Si des sous-expressions parenthses sont prsentes, lesoprateurs prsents dans celles-ci sont appliqus en premier

    L'ordre des priorits des oprateurs dj vus est le suivant (priorits

    ! -(oprateurs unaires) * / % + - < = > == != && ||

    Ainsi A + B * C est valu comme A + (B * C) Attention, tout programme qui dpend de l'ordre d'valuation des

    oprandes doit tre considr comme incorrect, car pour la plupart desoprateurs il n'existe aucune rgle et cela dpend du compilateur.

    3.1.5. Priorit des oprateurs : exemples

    a=1 ;x= (a=2) + a ;

    a=1 ;x = f(a=2) + g( a) ;

    /* 2 exemples incorrects,on ne sait pas si le second a vaut 1 ou 2 */

    printf("%d %d",++n, f(n))/* Incorrect car on ne peut pas savoir

    lequel de ++n et f(n) sera valu en premier */

  • Langage C - Jacoboni - 16/02/98 -21

    a[i] = i++ ; for (i=0; s1[i]; s2[i]=s1[i++]);/* Incorrect mais plus subtile */

    a[i++] = i; for (i=0 ; s1[i] ; s2[i]=s1[++i]);a[i] = ++i ; for (i=0 ; s1[i] ; s2[i++]=s1[i]);

    /* Correct */

    3.2. Autres oprateurs

    3.2.1. Oprateurs binaires Les oprateurs binaires ont des oprandes gnralement de type int,

    mais ils peuvent galement s'appliquer aux autres types entiers (char,short ou long, signs ou non).Ces oprateurs sont au ras de lamachine, ils servent manipuler des mots bit bit pour faire desmasques par exemple.

    a & b : et binaire (bit a bit) => mettre des bits 0unsigned n,c ;c=n & 0177 /* c sera constitu des 7 bits de poids faible

    de n et complt gauche par des 0 */ a | b : ou binaire => mettre des bits 1

    unsigned n,c ;c = n | 0177 /* c sera constitu des 7 bits de poids faible

    de n et complt gauche par des 1 */ a ^ b : ou exclusif binaire => inverser des bits

    unsigned n,c ;c = n ^ 0177 /* c sera constitu des bits de n, les 7 bits

    de poids faible tant inverss */ a > b : dcalage droiteLes bits de a sont dcals de b positions vers la droite, les bits de

    poids faible sont perdus, des bits X arrivent sur la gauche. si a est non sign ou sign positif : X=0; sinon (a ngatif) : pas de norme.

    ~a: complment 1 => les bits de a sont inverss.

    3.2.2. Oprateur d'affectation = est le symbole d'affectation l'affectation est une expression => elle renvoie une valeur gale la

    valeur de l'objet affect. On peut combiner l'affectation avec l'un des dix oprateurs suivant : + -

    * / % > & | ^ Cela peut permettre d'valuer une expression couteuse

    ex :Tab[indice(i)] = Tab[indice(i)] + n%k;Tab [indice(i)] += n % k ;

    Exemple : oprateur d'affectation et oprateurs binaires :int bitcount (unsigned int n){ /* compter les bits 1 dans n */

    int b ;for (b=0 ; n ; n >>=1 )

    if (n & 01) b++ ;return b ;

  • Langage C - Jacoboni - 16/02/98 -22

    }

    3.2.3. Oprateur conditionnel et oprateur de squence e1 ? e2:e3 est une expression qui vaut e2 si e1 est vraie et e3 sinon. e1, e2 est une expression qui vaut e2 mais dont l'valuation entraine

    au pralable celle de e1 (utilisation dans for).

    Exemple en C Equivalent Pascal i=0 ;while (i == N ? 0 :k=i, a[i++] != x) ;

    continue := true ; i:=0;while continue do begin if i=N then continue := false ; else begin

    k:=1; i:=i+1; if a[i-1] = x

    then continue:=false end

    end

    3.2.4. Oprateur d'appel de fonctions () Les arguments effectifs sont convertis lors de l'appel de la fonction. Le

    compilateur vrifie que le nombre d'arguments effectifs est gal aunombre d'arguments formels.

    3.2.5. Oprateur sizeof sizeof (x) donne la taille de x. Si x n'est pas un nom de type les parenthses sont facultatives. ex : int x, y, z;

    y=sizeof x; z=sizeof (int) ;

    Attention si x est une expression comme sizeof( i++) l'expression elle-mme n'est pas calcule.

    3.2.6. Oprateur de cast (t) a Le cast sert forcer le type d'un objet, c'est dire convertir un objet

    d'un type vers un autre. ex : (long int) x*y / (1. +sin(x))

    int f (float x){ return (int) x*x ;}

    3.3. Conversions numriquesOn peut se trouver face trois types de conversions La conversion intgrale o l'intgrit du nombre est prserve

    Un entier sign converti en un entier sign plus long un float converti en double

    La conversion conforme qui ne concerne que les entiers. L'entier change devaleur, mais la connaissance du type initial et de la valeur aprs conversion permetde reconstituer la valeur d'origine.

    Un entier court ngatif converti en entier non sign plus long La conversion dgradante o il y a perte dfinitive d'informations utiles

    Un entier est converti en entier plus court avec perte de bits significatifs. Un double est converti en float avec perte de bits significatifs dans la

    mantisse.

    3.4. Conversions implicites Promotion entire :

  • Langage C - Jacoboni - 16/02/98 -23

    Signs ou non, les char, short, champ de bits, numration sontimplicitement convertis en int ou unsigned int.

    Conversions d'arguments effectifs Lors de l'appel d'une fonction les arguments effectifs sont convertis dans le

    type des arguments formels dclars dans le prototype de la fonction. Conversions arithmtiques usuelles

    C'est se rapprocher du type "le plus grand" Exemple de conversion implicite

    int atoi (char s[])/*a(scii) to i(nteger) */{ int n = 0, i ;

    for (i=0; s[i] >= '0' && s[i]

  • Langage C - Jacoboni - 16/02/98 -24

    4. Quatrime Partie : Les Principales instructions Une instruction simple est une expression suivie d'un ; qui fait partie de l'instruction (ce

    n'est pas un sparateur comme en Pascal). Une instruction compose est une suite d'instructions encadre par {et}. Une instruction

    compose peut se mettre partout o l'on peut mettre une instruction.

    4.1. if syntaxe : if (expression) instruction

    si expression est vraie ( 0) instruction est excute Attention au pige de l'affectation, ne pas confondre ces deux programmes :

    int x,y;...y=f(...);if (x == y) ...........

    int x,y;...y=f(...);if (x = y) ...........

    4.2. if ... else Syntaxe : if (expression) instruction1 else instruction2

    instruction1 et instruction2 sont des instructions simples (penser au ; (Pascal)), ou des instructions composes.

    4.3. while Syntaxe : while (expression) instruction

    instruction est une instruction simple ou compose Il est frquent en C de voir une partie du travail ou la totalit reporte dans

    l'expression : while ((c=getchar())!= EOF)

    putchar(c) ; while (s[i++]) ;

    4.4. for Syntaxe : for ( expression1 ; expression2 ; expression3)

    instruction instruction est une instruction simple ou compose. expression1 sert initialiser expression2 est la condition de rebouclage expression3 est l'expression d'incrmentation

    Le for du C est un tantque traditionnel des autres langages. il peut dans la plupart1

    des cas tre rcrit de la faon suivante :expression1while (expression2)

    { instructionexpression3; }

    Les expressions peuvent comporter plusieurs instructionschar s[]="Coucou c\'est nous";int c,i,j;for ( i=0, j=strlen(s)-1 ; i

  • Langage C - Jacoboni - 16/02/98 -25

    Syntaxe : do instruction while (expression) ; Ceci est quivalent

    instructionwhile (expression)instruction

    Lorsque instruction est un bloc d'instructions simples, mettre {}

    4.6. break Cette instruction provoque la fin de l'instruction switch, while, do ou for qui la

    contient. (au premier niveau). Elle est utiliser avec prcaution et devra toujourstre justifie par des commentaires, comme toute autre instruction de rupture de

    4.7. continue Elle a pour but de provoquer le rebouclage immdiat de la boucle do, while ou for

    qui la contient. dans le cas d'un for (e1;e2;e3), e3 est value avant le rebouclage. C'est pour cette

    raison que l'quivalence entre le for et le while n'est pas totale.

    4.8. return; L'excution de la fonction qui contient le return est interrompu, le contrle est rendu

    4.9. return expression; Idem avec une valeur de retour gale l'valuation de expression.

    4.10. goto tiquette ; Ne pas utiliser sous peine de mort.

    4.11. switch syntaxe : switch (expression) {

    case c1 : instructions....

    default : instructions } L'expression et les diffrentes constantes (ci) doivent tres de type entiers, ou

    C'est diffrent du case Pascal, car les valeurs de la constante sont vues comme des

    switch (i) {case 1 : a=s[j];case 2 : b++;case 3 : a=s[j-1];}

    /* lorsque i vaut 1 les trois instructions sont excutes, quand i vaut 2 ce sont lesdeux dernires (b++ et a=s[j-1]). */

    Pour viter cela, il faut utiliser la fonction breakswitch (i) {

    case 1 : a=s[j];break;case 2 : b++;break;case 3 : a=s[j-1]; /* le dernier break est inutile */}

    Il n'y a pas de possibilit de donner d'numrations de valeurs ou d'intervalles

  • Langage C - Jacoboni - 16/02/98 -26

    5. Cinquime Partie : La programmation en C

    5.1. Les Fonctions

    5.1.1. Prsentation gnrale Une fonction est une portion de programme formant un tout homogne,

    destin remplir une certaine tche bien dlimite. Lorsquun programme contient plusieurs fonctions, lordre dans lequel

    elles sont crites est indiffrent, mais elles doivent tre indpendantes. En rgle gnrale, une fonction appele a pour rle de traiter les

    informations qui lui sont passes depuis le point dappel et deretourner une valeur. La transmission de ces informations se fait aumoyen didentificateurs spcifiques appels arguments et la remontedu rsultat par linstruction return.

    Certaines fonctions reoivent des informations mais ne retournent rien(par exemple printf), certaines autres peuvent retourner un ensemblede valeurs (par exemple scanf).

    5.1.2. Dfinition de fonction La dfinition dune fonction repose sur trois lments

    Son type de retour La dclaration de ses arguments formels Son corps

    De faon gnrale, la dfinition dune fonction commence donc par :type_retour nom (type-arg-f1 arg-f1, type-arg-f2 arg-f2 ...)

    Les arguments formels permettent le transfert dinformations entre lapartie appelante du programme et la fonctions. Ils sont locaux lafonction, et lors de lappel ils seront mis en correspondance avec lesarguments effectifs.

    Contrairement dautres langages, le C ne permet pas la modificationLe seul mode de passage des

    paramtres est le mode par valeur. Cela signifie que les valeursdes paramtres effectifs sont copies dans les paramtres formels .

    Linformation retourne par une fonction au programme appelant esttransmise au moyen de linstruction return, dont le rle est galementde rendre le contrle de lexcution du programme au point o a t

    La syntaxe gnrale de la fonction return est la suivante :return expression ;

    5.1.3. Dclaration de fonction Lorsque lappel dune fonction figure avant sa dfinition, la fonction

    appelante doit contenir une dclaration de la fonction appele. Onappelle cela prototype de la fonction.

    Attention a ne pas confondre dfinition et dclaration defonctions. La dclaration est une indication pour le compilateurquant au type de rsultat renvoy par la fonction et ventuellement autype des arguments, et rien de plus.

    Dans sa forme la plus simple la dclaration dune fonction peut : type_de_retour nom () ;

    Les prototypes de fonctions sont souvent regroupes par thmes dansdes fichiers dont lextension est gnralement h (ex stdio.h). Cesfichiers sont inclus dans le source du programme par une directive du

  • Langage C - Jacoboni - 16/02/98 -27

    prprocesseur : #include. Cette mthode permet de dfinir desprototypes globaux au programme.

    5.1.4. Un programme complet en C(A faire en TD ou en TP) Simulation dun jeu de hasard (jeu de d). Il sagit ici dun exemple

    intressant de programme dans lequel figurent plusieurs appels defonctions diffrents niveaux. Sont appeles aussi bien des fonctionsexternes que des fonctions personnalises provenant de bibliothquesdu programmeur.

    Le craps est un jeu o lon lance plusieurs reprise une paire de ds,aussi longtemps que lon gagne. Ce jeu peut tre simul sur unordinateur en remplaant le lancer de ds par un tirage de nombres

    Il existe deux cas de russite : On gagne soit en obtenant un total de 7ou 11 au premier lancer, soit en obtenant un total de 4,5,6,8,9 ou 10,auquel cas on lance nouveau les ds jusqu' rpter ce mme totalet condition de ne jamais obtenir 7. Il existe par consquent deux

    : Soit en obtenant un total de 2,3, ou 12 au premieressai, soit en obtenant dabord un total de 4,5,6,8,9 ou 10, suivi dunou plusieurs lancers jusqu' obtenir un total de 7 avant davoirretrouver le total du premier lancer.

    Le jeu simul doit tre interactif, de sorte que chaque lancer soitdclench par le joueur en pressant une touche du clavier. Le rsultatde chaque lancer est affich par un message. A la fin de la partie,lordinateur demande lutilisateur sil souhaite rejouer.

    5.1.5. Rcursivit La rcursivit est la caractristique des fonctions capables de

    sappeler elles-mmes de faon rptitive, jusqu ce que soit vrifieune condition darrt. Le C permet dcrire des fonctions rcursives.

    Exemple Affichage renvers dun texte.#include void main() {

    void renverse(void) ;printf (" Saisir une ligne de texte ci-dessous \n " ) ;renverse() ;

    }/* Lecture dune ligne et affichage en sens inverse */void renverse (void) {

    char c ;if ((c = getchar()) != \n )

    renverse() ;putchar(c) ;return ;

    }

  • Langage C - Jacoboni - 16/02/98 -28

    5.2. Structure des programmes Dans certains contextes il peut tre ncessaire de disposer de variables globales

    utilisables sur la totalit, ou une partie seulement du programme. Ce type devariable doit tre dfinie diffremment des variables dites "locales", dont la portene dpasse pas la fonction dans laquelle elles sont dfinies.

    Il peut tre galement possible de conserver certaines informations dans desvariables locales, aussi bien de faon statique que dynamique.. En effet, par dfautla valeur d'une variable locale est perdue l'issue de la fonction dans laquelle elle

    Enfin il peut tre ncessaire de dvelopper des programmes de grande taille, faisantappel de multiples fonctions rparties dans divers fichiers sources. Dans ce typede programmes, les fonctions peuvent tre dfinies et appeles aussi bien de faonlocale, dans un mme fichier, que globale, depuis des fichiers distincts.

    5.2.1. Classe de mmorisation Une variable est caractrise par deux lments qui sont : le type de

    donne et la classe de mmorisation. Le type de la donne fait rfrence la nature des informations que

    contiendra la variable. (un entier, un rel ...) La classe de mmorisation fait rfrence la prennit (permanence)

    d'une variable, et sa visibilit dans le programme. Il existe en C, quatre classes de mmorisation : automatique, externe,

    statique ou registre, identifies respectivement par les mots clsauto, extern, static et register

    La classe de mmorisation attache une variable peut parfois tredtermine par la seule localisation de la dclaration de cette variabledans le programme. Dans les autres cas le mot cl explicite la classe

    Exemples : auto int a, b, c ; Var automatiques entires extern float racine1, racine2 ;Var externes de type relles static int compteur = 0 ; Var entire statique initialise 0 extern char etoile ; Var externe caractre

    5.2.2. Variables de classe automatique Les variables de classe automatique sont toujours dclares au sein

    dune fonction, pour laquelle elle joue le rle de variable locale. Leurporte est limite cette seule fonction. Cest le mode par dfaut, donc

    auto est facultatif. Ces variables peuvent tre initialises en incluant les expressions

    adquates dans leur dclaration. La valeur dune variable de classeauto nest pas conserve dun appel lautre de la fonction.

    Il est possible de rduire la porte dune variable automatique unetendue infrieure celle de la fonction. Il faut la dfinir pour cela dansune instruction compose, sa dure de vie est alors celle de

    5.2.3. Variables de classe externe Les variables de classe externe au contraire des variables de classe

    automatique ne sont pas limites la seule tendue dune fonction.Leur porte stend de lendroit o elles sont dfinies la fin duprogramme. Elles constituent en C ce quon appelle une variable

  • Langage C - Jacoboni - 16/02/98 -29

    Une variable externe peut par consquent se voir affecter une valeurdans une fonction, valeur qui pourra tre accde depuis une autrefonction. (Attention aux dangers !!)

    Lorsque lon utilise des variables externes il est important dediffrencier leur dfinition et leur dclaration. La dfinition dunevariable externe scrit comme la dfinition de nimporte quelle autrevariable ordinaire. Elle doit se situer en dehors et en amont desfonctions qui utiliseront la variable. Elle ne doit pas contenir le motcl extern (compiler dependent).

    Toute fonction utilisant une variable externe doit comporter unedclaration explicite de cette variable, (obligatoire si la fonction estdfinie avant la variable, facultatif si la fonction est dfinie aprs, maisobligatoire si cest Jacoboni qui corrige la copie !). Cette dclaration setraduit par la rptition de la dfinition prcde du mot cl extern.

    Aucune allocation de mmoire nest faite la suite dune dclarationpuisque cette allocation est faite une fois pour toute lors de la dfinitionde la variable. Ceci explique quil nest pas possible dinitialiser unevariable externe au moment de sa dclaration, mais uniquement lors

    Les variables externes peuvent tre initialises dans leur dfinition,mais leur valeur initiale doit tre une constante. (En aucun cas uneexpression). En l'absence de toute initialisation explicite, les variablesexternes sont automatiquement initialises 0. Il est cependantprfrable dexpliciter dans la dfinition, linitialisation 0 lorsquelle

    Les Tableaux peuvent tre galement de classe automatique ouexterne, mais il nest pas possible dinitialiser un tableau de classeautomatique.

    Il est important de souligner les risques inhrents lusage desvariables externes, en particulier les effets de bords. Ces variablessont souvent la source derreurs difficiles identifier. Le choix par leprogrammeur des classes de mmorisation doit donc tre effectu defaon rflchie, pour rpondre des situations bien dtermines.

    5.2.4. Variables de classe Statique des programmes monofichiers Les variables statiques sont dfinies dans les fonctions comme en

    automatique et ont donc la mme porte. (Locale la fonction). Par contre, ces variables conservent leur valeur durant tout le cycle du

    programme. Ce sont des variables rmanentes. On les dfinit de la mme faon que les variables automatique sauf

    que leur dclaration doit commencer par le spcificateur de classestatic.

    Les dfinitions de variables statiques peuvent contenir des affectationsde valeurs initiales qui doivent respecter les points suivants :

    a) Les valeurs initiales doivent tre des constantes et pas desexpressions,

    b)En labsence de valeur initiale, une variable statique est toujoursinitialise 0.

  • Langage C - Jacoboni - 16/02/98 -30

    5.3. Communication entre modules Une application peut tre conue comme une collection de modules, chaque module

    : Une collection de sous-programmes, Une collection de donnes partages, Un objet abstrait possdant une reprsentation et offrant des oprateurs

    de manipulation. De tels modules peuvent constituer des units de programme en C. Mmorise dans

    un fichier, une unit de programme constitue une unit de compilation. Aprs compilation de toutes les units constituant lapplication, lditeur de lien a pour

    tche de rassembler les divers modules rsultats des compilations (modules objets)afin de constituer laplication totale.

    Il est donc ncessaire dtablir un protocole de communication entre les diversmodules. Il permet de spcifier dans le programme source, les liens tablir entre

    5.3.1. Rgles de communication On dit quune variable ou une fonction est partage entre deux modules

    lorsquelle est utilise dans ces deux modules. En C seules les variablesglobales peuvent tre partages entre deux modules. Par contre, toutefonction peut tre partage entre deux modules.

    Dans le module o la variable est dfinie, une dfinition introduitlidentificateur de la variable, son type et ventuellement une valeurinitiale. La variable est visible dans tout le module, partir du point de

    Dans un autre module o la variable est utilise, une dclarationintroduit lidentificateur de type de la variable. Cette dclaration doit tre

    extern. La variable est alors visible dans tout lemodule partir du point de cette dclaration.

    ExempleModule 1 Module 2

    int v= 23 ; /* Variable val de module 2 */extern int val ; /* fonction fonct de module 2 */extern int fonct()main() {....}

    int val = 100 ;int fonct (int p) { /* variable v de module 1 */ extern int v ; ..........}

    Une fonction dfinie dans un module peut tre manipule dans un autremodule, a condition davoir effectu une dclaration dimportation dansle second module.

    Il est des cas o on ne dsire pas que les symboles dfinis dans unmodule soient accessibles dans un autre module. Pour cela on utilise leprfixe static.

    ExempleModule 1 static int V = 0 ; /* Variable locale au module 1 */Module 2 int V = 0 ; /* Variable exportable */Module 3 extern int V ; /* Variable V dfinie dans le module 2 */

  • Langage C - Jacoboni - 16/02/98 -31

    5.4. Utilisation de make Lutilitaire make permet de maintenir une application multi-fichiers, en sappuyant sur

    les dates des dernires modifications des fichiers. Il dispense lutilisateur davoir sesouvenir :

    Des relations existant entre les fichiers, Des fichiers rcemment modifis, Des fichiers recompiler, Des oprations effectuer pour construire lapplication.

    En effet, lorsquune composante est modifie, un appel make permet de ractualiserautomatiquement les fichiers qui ont besoin de ltre. Pour cela, make sappuie sur unfichier (le makefile) qui dcrit une fois pour toutes les relations entre les fichiers et lesactions entreprendre pour les mises jour.

    Le fichier en cours de ractualisation est appel cible. Le traitement effectu parmake , pour le fichier cible courant comporte 3 tapes :

    Trouver dans le fichier description les lignes qui concernent la cible, sassurer que tous les fichiers dont dpend la cible existent et sont jour, crer si ncessaire la cible.

    5.4.1. La syntaxe du makefile Le fichier description comporte une squence denregistrements

    spcifiant les relations entre fichiers. Un enregistrement occupe une ouplusieurs lignes, selon le schma suivant ( dsigne le caractre detabulation).

    Cibles : FICHIERS_PREREQUIS ; COMMANDE COMMANDE................. COMMANDE

    Une commande qui occupe plusieurs lignes peut tre poursuivie sur laligne suivante en terminant la ligne par le caractre \

    Le plus dlicat dans lcriture du makefile consiste a dterminer lesrelations entre les fichiers.

    Exemple : considrons une application dont le programme executableest contenu dans le fichier applic.out. Les sources C correspondantsont dans les fichiers sleep.c et test_sleep.c. Le fichier de descriptionsuivant (makefile1) permet de maintenir automatiquement une telleapplication.

    applic.out : test_sleep.o sleep.occ test_sleep.o sleep.o -o applic.out

    test_sleep.o : test_sleep.ccc -c test_sleep.c

    sleep.o : sleep.ccc -c sleep.c

    Utilisation :$ ls sleep.o test_sleep.o

    sleep.o not found Les fichiers nexistenttest_sleep.o not found pas

    $ make -f makefile1cc -c test_sleep.ccc -c sleep.ccc test_sleep.o sleep.o -o applic.out

    $ ls sleep.o test_sleep.o applic.out

  • Langage C - Jacoboni - 16/02/98 -32

    applic.out sleep.o test_sleep.o Ces fichiers ont t crs$ make -f makefile1

    applic.out is up to date. Supposons maintenant quune modification est faite dans le fichier

    sleep.c. il est alors ncessaire de reconstruire lapplication$ make -f makefile1

    cc -c sleep.c test_sleep.c nest pas recompilcc test_sleep.o sleep.o -o applic.out

  • Langage C - Jacoboni - 16/02/98 -33

    6. Sixime partie : Les Pointeurs et les Tableaux Un pointeur, en C comme en PASCAL, est une adresse permettant de dsigner un objet

    (une variable ou une fonction) en mmoire centrale. Par extension, on appelle pointeur la variable qui contient cette adresse.

    6.1. Pointeurs et adresses Un pointeur dfinissant l'adresse d'un objet, l'accs cet objet peut alors tre ralis par

    une indirection sur le pointeur. L'oprateur unaire & fournit l'adresse de l'objet oprande (qui doit donc tre une

    lvalue2). On dit aussi que cet oprateur est l'oprateur de . L'oprateur unaire * considre son oprande comme un pointeur et retourne

    l'objet point par celui-ci. On dit aussi que cet oprateur est l'oprateurd'indirection.

    Exemples :int X, Y;/* Soit PX un pointeur sur des int */PX = &X; /* PX

  • Langage C - Jacoboni - 16/02/98 -34

    La valeur NULL, est une valeur de pointeur, constante et prdfinie dans stddef.h.Elle vaut 0 et signifie "Aucun objet". Cette valeur peut tre affecte tout pointeur,quel que soit son type.

    En ce cas, ce pointeur ne pointe sur rien... Bien entendu, l'utilisation de cette valeur dans une indirection provoquera une

    erreur d'excution.

    L'affectation d'un pointeur un autre n'est autorise que si les 2 pointeurs pointent lemme type d'objet (ie ont le mme type)

    Exemple :P = NULL;P = Q; /* P et Q sont de pointeurs sur le mme type */P = 0177300; /* illgal */P = (int *) 0177300;/* lgal */

    L'incrmentation d'un pointeur par un entier n est autorise. Elle ne signifie surtoutpas que l'adresse contenue dans le pointeur est incrmente de n car alors cetteadresse pourrait dsigner une information non cohrente : tre cheval sur 2 motspar exemple...

    L'incrmentation d'un pointeur tient compte du type des objets points par celui-ci :elle signifie "passe l'objet du type point qui suit immdiatement en mmoire". Cecirevient donc augmenter l'adresse contenue dans le pointeur par la taille des objets

    Dans le cas d'une valeur ngative, une dcrmentation a lieu.

    Les oprateurs combins avec l'affectation sont autoriss avec les pointeurs. Il en vade mme pour les incrmentations / dcrmentations explicites.

    Exemples :int *Ptr, k; /* Ptr est un pointeur , k est un int */

    Ptr++;Ptr += k;Ptr--;Ptr -= k;

    6.3. Comparaison de pointeurs

    Il est possible de comparer des pointeurs l'aide des relations habituelles : < >=== !=

    Cette opration n'a de sens que si le programmeur a une ide de l'implantation des

    Un pointeur peut tre compar la valeur NULL.Exemples :

    int *Ptr1, *Ptr2;......if (Ptr1

  • Langage C - Jacoboni - 16/02/98 -35

    Autrement dit, la diffrence entre 2 pointeurs fournit la valeur entire qu'il faut ajouterau deuxime pointeur (au sens de l'incrmentation de pointeurs vue plus haut) pourobtenir le premier pointeur

    6.5. Affectation de chanes de caractres

    L'utilisation d'un littral chane de caractres se traduit par la rservation en mmoirede la place ncessaire pour contenir ce littral (complt par le caractre '\0') et laproduction d'un pointeur sur le premier caractre de la chane ainsi mmorise.

    Il est alors possible d'utiliser cette valeur dans une affectation de pointeurs.Exemple :

    char *Message;Message = "Langage C";/* est autoris */

    /* La chane est mmorise et complte par '\0'. La variable Message reoit l'adresse

    6.6. Pointeurs et tableaux

    On rappelle que la dclaration d'un tableau dans la langage C est de la forme : intTab[10];

    Cette ligne dclare un tableau de valeurs entires dont les indices varieront de la

    En fait, cette dclaration est du "sucre syntaxique" donn au programmeur. En effet,de faon interne, elle entraine :

    La dfinition d'une valeur de pointeur sur le type des lments du tableau,cette valeur est dsigne par le nom mme du tableau (Ici Tab)

    La rservation de la place mmoire ncessaire au 10 lments du tableau,allous conscutivement. L'adresse du premier lment (Tab[0]) dfinit lavaleur du pointeur Tab.

    La dsignation d'un lment (Tab[5] par exemple) est automatiquement traduite, parle compilateur, en un chemin d'accs utilisant le nom du tableau (Dans notre exemplece serait donc *(Tab + 5))

    Exemples :int *Ptab, Tab[10];

    On peut crire :Ptab = &Tab[0];Ptab = Tab; /* Equivalent au prcdent */Tab[1] = 1;*(Tab + 1) = 1; /* Equivalent au prcdent */

    Donc, pour rsumer, on a les quivalences suivantes :Tab + 1 est quivalent &(Tab[1])*(Tab + 1) est quivalent Tab[1]*(Tab + k) est quivalent Tab[k]

    Aucun contrle n'est fait pour s'assurer que l'lment du tableau existeeffectivement :

    Si Pint est gal &Tab[0], alors (Pint - k) est lgal et repre un lment hors desbornes du tableau Tab lorsque k est strictement positif.

    Le nom d'un tableau n'est pas une lvalue, donc certaines oprations sontimpossibles (exemple : Tab++)

  • Langage C - Jacoboni - 16/02/98 -36

    Application :#include main(){ char Tab[32], *Ptr;

    /* Initialisation des donnes */Tab[0] = 'Q'; Tab[1] = 'W'; Tab[2] = '\0';Ptr = "ASDFGHJKL";

    /* Edition des chaines */printf("Contenu des chaines : \n");printf(" Tab : %s\n Ptr : %s\n", Tab, Ptr);

    /* Utilisation des tableaux */printf("Edition de l'lment de rang 1 des tableaux\n");printf(" Tab : %c\n Ptr : %c\n", Tab[1], Ptr[1]);

    /* Utilisation des pointeurs */printf("Edition du caractre point\n");printf(" Tab : %c\n Ptr : %c\n",*Tab, *Ptr);

    /* Utilisation des pointeurs incrments */printf("Edition du caractre suivant le caractre point\n");printf(" Tab : %c\n Ptr : %c\n", *(Tab + 1), *(Ptr + 1));

    /* Rgle des priorits */printf ("Edition identique non parenthse \n");printf(" Tab : %c\n Ptr : %c\n", *Tab + 1, *Ptr + 1);}

    En sortie, on aura :Contenu des chaines :Tab : QWPtr : ASDFGHJKLEdition de l'lment de rang 1 des tableauxTab : WPtr : SEdition du caractre point :Tab : QPtr : AEdition du caractre suivant le caractre pointTab : WPtr : SEdition identique non parenthse :Tab : RPtr : B

    6.7. Passage des paramtres

    le seul mode de passage des paramtres une fonction est le passage par valeur.

    Le problme est que lorsqu'un sous-programme doit fournir une rponse par un deses paramtres, ou modifier ceux-ci, le mode de passage par valeur ne peut plusconvenir.

    De plus, dans le cas de paramtres structurs de taille importante, la copie de ceux-cientraine une consommation mmoire parfois superflue.

  • Langage C - Jacoboni - 16/02/98 -37

    C'est la charge du programmeur de grer tous ces problmes en fournissant unpointeur sur l'objet en question, ce qui non seulement permet au sous-programme detravailler directement sur l'objet rel et donc de le modifier, mais aussi rduit la tailledes changes, puisqu'il n'y a copie que d'une adresse.

    Exemple classique :#include void Echange_1 (A,B)int A,B;{ int C = A; A = B; B = C;}

    void Echange_2 (A,B)int *A,*B;{ int C = *A; *A = *B; *B = C;}

    main(){ int X, Y; printf("Valeur de X : "); scanf ("%d",&X); printf("\nValeur de Y : "); scanf ("%d",&Y); Echange_1 (X,Y) printf("\nAprs appel de Echange_1 :\n X = %d\n Y = %d\n", X, Y); Echange_2 (&X,&Y) printf("Aprs appel de Echange_1 :\n X = %d\n Y = %d\n", X, Y);}

    Ce qui produit l'excution :

    Valeur de X : 12Valeur de Y : 34Aprs appel de Echange_1 :X = 12Y = 34Aprs appel de Echange_2 :X = 34Y = 12

    Quand un tableau est transmis comme paramtre effectif un sous-programme,c'est en fait l'adresse de base de ce tableau qui est transmise par valeur.

    Ceci a pour effet de transmettre le tableau par rfrence sans intervention duprogrammeur.

    De plus, l'intrieur de la fonction appele, le paramtre tableau devient unelvalue, certaines oprations sont donc possibles.

    Exemple :#include void Test_Tab (T)int T[5];{ printf(" Editions dans la fonction \n");

  • Langage C - Jacoboni - 16/02/98 -38

    printf(" Valeur du paramtre tableau : %o \n",T); printf(" Valeur du contenu : %d\n",T[0]); printf(" Test d'incrmentation paramtre \n"); T++; /* T est devenue une lvalue */ printf(" Valeur du paramtre tableau : %o \n",T);}

    main(){ int Tab[5]; Tab[0] = 10; printf("Editions avant appel de fonction\n"); printf(" Valeur du paramtre tableau : %o\n",Tab); printf(" Valeur du contenu : %d\n",Tab[0]); Test_Tab(Tab);}

    Exemple de sortie :

    Editions avant appel de fonction Valeur du paramtre tableau : 177514 Valeur du contenu : 10Editions dans la fonction Valeur du paramtre tableau : 177514 Valeur du contenu : 10 Test d'incrmentation paramtre Valeur du paramtre tableau : 177516

    6.8. POINTEURS ET TABLEAUX MULTIDIMENSIONNELS

    Un tableau unidimensionnel peut se reprsenter grce un pointeur (le nom dutableau) et un dcalage (lindice).

    Un tableau plusieurs dimensions peut se reprsenter l'aide d'une notationsimilaire, construite avec des pointeurs.

    Par exemple, un tableau de dimension 2, est en fait un ensemble de deux tableaux une seule dimension. Il est ainsi possible de considrer ce tableau deux dimensionscomme un pointeur vers un groupe de tableaux unidimensionnels conscutifs. Ladclaration correspondante pourra scrire de la manire suivante:

    type-donne (*varpt)[expression 2];au lieu de la dclaration classique:

    type-donne tableau [expression l][expression 2];

    Ce style de dclaration peut se gnraliser un tableau de dimension n de la faonsuivante:

    type-donne (*varpt)[expression 2][expression 3] ... [expression n];qui remplace la dclaration quivalente:

    type-donne tableau[expression 1][expression 2] ... [expression n];

    Dans ces dclarations, type-donne dsigne le type du tableau, varpt est le nom dupointeur vers le tableau, tableau est le nom du tableau correspondant, et expression1, expression 2,...expression n sont des expressions entires positives qui spcifientle nombre maximum dlments associs chacune des dimensions.

    On remarquera les parenthses qui encadrent le nom du tableau, ainsi quel'astrisque qui introduit le pointeur. Ces parenthses sont indispensables, car sans

  • Langage C - Jacoboni - 16/02/98 -39

    leur prsence, on dfinirait un tableau de pointeurs, au lieu d'un pointeur vers unensemble de tableaux, puisque les symboles [ ] et * s'valuent normalement de droite

    Exemple : On suppose que x est un tableau d'entiers de dimension 2, ayant 10 ligneset 20 colonnes. On peut le dclarer de la faon suivante:

    int (*x) [20]; au lieu de int x[10] [20];

    Dans la premire dclaration, on dit que x est un pointeur vers un groupe de tableauxd'entiers contigus, possdant chacun une dimension et 20 lments. Ainsi, x pointe lepremier tableau de 20 lments, qui constitue en fait la premire ligne (ligne 0) dutableau d'origine de dimension 2. De manire analogue. (x+1) pointe vers ledeuxime tableau de 20 lments, qui reprsente la seconde ligne (ligne 1) dutableau d'origine, et ainsi de suite

    Si l'on considre prsent un tableau tridimensionnel de rels, t, on peut le dfinirpar:

    float (*t) [20] [30]; au lieu de float t[10] [20] [30];

    La premire forme dfinit t comme un pointeur vers un groupe contigu de tableaux derels, de dimension 20 x 30. Dans ce cas t pointe le premier tableau 20 x 30, (t+1)pointe le second tableau 20x30, etc.

    Pour accder un lment donn d'un tableau plusieurs dimensions, on appliqueplusieurs fois l'oprateur d'indirection. Mais cette mthode est souvent plus pnibled'emploi que la mthode classique.

    Exemple : x est un tableau d'entiers de dimension 2, 10 lignes et 20 colonnes.L'lment situ en ligne 2 et colonne 5 peut se dsigner aussi bien par :

    x[2] [5] que par * (* (x+2) +5)

    Explications : (x+2 ) est un pointeur vers la ligne 2, donc * (x+2) reprsente la ligne 2 toute

    entire. Puisque la ligne 2 est elle-mme un tableau, * (x+2) est aussi un pointeur vers

    son premier lment. On ajoute ensuite 5 ce pointeur. L'expression (* (x+2) +5) donne donc un

    pointeur vers l'lment 5 (le sixime) de la ligne 2. L'objet dsign par ce dernier pointeur, * ( * (x+2 ) +5 ) est donc bien llment

    cherch, en colonne 5 de la ligne 2, ou bien encore x [2] [5] .

    x

    x+1

    x+2

    * ( x + 2 ) * ( x + 2 ) + 5

    * ( *(x+2) + 5 )

  • Langage C - Jacoboni - 16/02/98 -40

    Les programmes mettant en jeu des tableaux multidimensionnels peuvent scrire deplusieurs manires diffrentes. Choisir entre ces formes relve surtout des gotspersonnels du programmeur.

    6.9. Reprise des premiers exercices de TD.Exercice 4

    Ecrire une fonction Reverse (s) qui inverse une chaine s passe en paramtre. Ecrireun programme utilisant cette fonction.

    #include #include

    void main(){

    void Reverse (char*) ;char *chaine="Je suis content d\'tre en Td de C";

    printf ("\n%s",chaine) ; /* avant */Reverse (chaine) ; ;printf("\n%s",chaine) ; /* aprs */

    }

    void Reverse (char *s){

    int c,i,j ;for (i=0, j=strlen(s) -1; i

  • Langage C - Jacoboni - 16/02/98 -41

    Les pointeurs tant des informations comme les autres, ils peuvent tre mis dans destableaux.

    Exemple : char *Ptr_Char[7];

    Cette dclaration se lit comme : Ptr_Char est un tableau dont les lments sont dutype char*. Les 7 lments de Ptr_Char sont donc des pointeurs vers des caractres

    D'aprs ce qui a t vu prcdemment cela signifie que chaque lment du tableaupeut pointer vers une chane de caractres.

    On conoit qu'avec une telle reprsentation, une permutation de chane est trs facilepuisqu'il suffit de permuter les pointeurs correspondants.

    De plus, les diffrentes chanes peuvent avoir des tailles diffrentes, ce qui ne seraitpas possible si l'on dclarait un tableau de caractres 2 dimensions comme :

    char Tab_Char[7][10]

    On peut initialiser un tableau de pointeur de la faon suivante :char *Ptr_Char[7] = {"Lundi", "Mardi", "Mercredi", "Jeudi","Vendredi", "Dimanche"};

    et on pourrait l'utiliser ainsi :for (i = 0; i

  • Langage C - Jacoboni - 16/02/98 -42

    malloc renvoie un pointeur universel (void *) vers le dbut de la zone alloue de toboctets.

    calloc renvoie un pointeur universel (void *) vers le dbut de la zone alloue de nobobjets de taille tob octets (tableau dynamique).

    realloc permet de modifier la taille d'une zone prcdemment alloue.

    Ces trois fonctions renvoient NULL si l'allocation a chou.

    free rend au systme (dsalloue) la zone pointe par le pointeur paramtre. Si cepointeur a dj t dsallou ou s'il ne correspond pas une valeur alloue parmalloc, calloc ou realloc, il y a une erreur.

    Le comportement du systme est alors imprvisible.

    Exemple : Une fonction qui reoit en argument un pointeur initialiser par malloc etqui renvoie un boolen indiquant si l'allocation s'est bien passe.

    int alloc (int **p) /* p est un pointeur de pointeur d'entier */{

    *p=(int *) malloc (sizeof (int)) ;return *p != NULL ;

    }main (){...

    int *pp ;p=NULL ;if (alloc (&pp))/* adresse du pointeur */

    *p=5 ;/* pp a t modifi par alloc */....... /* il n'est plus NULL */}

  • Langage C - Jacoboni - 16/02/98 -43

    7. Septime partie : Structures et Unions

    On a dj vu que le constructeur tableau permettait de regrouper plusieurs lments.Toutefois, ceux-ci devaient tre tous du mme type.

    Le constructeur structure permet de regrouper de lments de types diffrents.

    De plus, ce constructeur permet de dfinir des modles d'objets alors que dans le casd'un tableau les objets sont anonymes.

    7.1. Dclaration de structureSyntaxe : struct identificateur

    {liste de champs

    };Exemple : struct Quidam

    {char *Nom;int Age;float Taille;

    };

    Les composants d'une structure sont appels champs de la structure.

    Une telle dclaration dfinit un modle d'objet. Elle n'engendre pas de rservationmmoire. Le modle ainsi dfini peut tre utilis dans une dclaration de variable.

    Exemple : struct Quidam Michel, Anne; /* Dclare 2 objets */

    Remarque : Dans une structure, tous les noms de champs doivent tre distincts. Parcontre rien n'empche d'avoir 2 structures avec des noms de champs en commun :l'ambiguit sera leve par la prsence du nom de la structure concerne.

    7.2. Initialisation de structure

    Une dclaration d'objet structure peut contenir une initialisation. Mais alors, ladclaration doit tre globale ou statique.

    La valeur initiale est constitue d'une liste lments initiaux (1 par champ) placeentre accolades.

    Exemple :struct Quidam Jean = {"Dupont" , 35, 1.80};

    7.3. Accs un champSyntaxe : .

    L'oprateur d'accs est le symbole "." (point) plac entre l'identificateur de la structureet l'identificateur du champ dsign.

    Exemples :Michel.Age = 45;...T_19_25 = (Michel.Age >= 19) && (Michel.Age

  • Langage C - Jacoboni - 16/02/98 -44

    struct Quidam{ char *Nom,

    *Adresse; struct Date Naissance;};

    struct Quidam Michel = {"Dupont", "Rue Lamarck", {21,05,60} };On peut alors crire :

    if (Michel.Naissance.Jour == 20) ...

    Sur les compilateurs C respectant la norme ansi, il est possible daffecter lintgralitdes valeurs dune structure une seconde structure ayant imprativement la mmecomposition.

    Exemple :

    struct bidon a , b ;

    a=b est une instruction valide, qui recopie tous les champs de b dans les champsde a.

    Attention la recopie est superficielle.

    7.5. Tableaux de structures

    Un modle structure peut aussi apparatre comme type des lments d'un tableau.

    Exemple :struct Entree

    {char *Symbole;int ldef;char *Info;

    };...struct Entree Tds[20]; /* tableau de 20 structures */Tds[12].Symbole = "Jean";

    7.6. Structures et pointeurs

    Le type associ un pointeur peut tre une structure.

    Exemple :struct Date *Ptr_Date; /* Ptr_Date pointe sur des objets de type Date */

    Il est alors possible d'utiliser ce pointeur de la faon suivante :Ptr_Date->Jour = 12; /* quivaut (*Ptr_Date).Jour */

    7.7. Passage de structures comme arguments de fonctions

    La norme ansi a introduit le transfert direct dune structure entire comme argumentdune fonction, ainsi que la remonte de cette structure depuis une fonction appelevia une instruction return.

    Le passage de paramtres de type structure se fait par valeur.

    Sur certains compilateur ancien on doit passer et retourner des pointeurs sur lesstructures.

  • Langage C - Jacoboni - 16/02/98 -45

    7.8. Structures rcursives

    Ce genre de structures est fondamental en programmation car il permetd'implmenter la plupart des structures de donnes employes en informatique (filesd'attente, arborescences, etc...)

    Exemple :struct Individu

    {char *Nom;int Age;struct Individu Pere, Mere;};

    /* Cette dfinition est incorrecte : la taille de Pere et Mere n'est pas connue */

    struct Individu{char *Nom;int Age;struct Individu *Pere, *Mere;};

    7.9. Les Unions

    Une dclaration d'union se prsente comme une dclaration de structure. Mais, alorsqu'un objet structur est compos de la totalit de ses champs, un objet union estconstitu d'un seul champ choisi parmi tous les champs dfinis.

    Exemple :union Int_Float

    {int i;float f;};

    union Int_Float X;

    A un instant donn, l'objet X contiendra un entier ou un flottant, mais pas les deux !C'est au programmeur de connatre tout instant le type de l'information contenuedans X.

    L'accs cette information se fait de faon analogue l'accs un champ destructure.

    Le programmeur utilisera X.i s'il dsire manipuler l'infomation de type int, sinon ilutilisera X.f

    Un objet de type union occupe une place gale celle du plus grand de son champ.Ainsi si, par exemple, un int occupe 2 octets et un float 5 octets, alors l'objet Xoccupera 5 octets.

    ATTENTION !!!

    Ce constructeur peut tre la source d'erreurs trs difficiles dtecter.

    Donc, manier avec prcaution et seulement en cas de besoin .

  • Langage C - Jacoboni - 16/02/98 -46

    7.10. Schmas d'implantation

    Le C permet de prciser l'implantation mmoire d'une structure. Ceci estparticulirement intressant pour reprsenter des informations proches du niveaumatriel comme par exemple le registre d'tat du CPU.

    Exemple :struct Status_Register

    { unsigned E : 1; unsigned F : 1; unsigned H : 1; unsigned I : 1;/* Mot d'tat du 6809 */ unsigned N : 1; unsigned Z : 1; unsigned V : 1; unsigned C : 1;};

    Seuls des champs de type unsigned sont autoriss

    Chaque nom de champ est suivi du symbole ":" et d'un entier reprsentant la taille enbits de ce champ. L'accs aux champs suit les mmes rgles que pour une structureclassique. Cependant l'oprateur & (Rfrence ) ne peut tre appliqu un telchamp (il peut l'tre sur la structure globale)

  • Langage C - Jacoboni - 16/02/98 -47

    8. Huitime partie : Entres / sorties En C les E/S relvent de la bibliothque standard et pas du langage lui-mme qui est

    Le traitement des E/S repose sur 3 lments : le type FILE dfini dans stdio.h Trois variables de type FILE * :

    stdin : entre standard, stdout : sortie standard, stderr : sortie standard d'erreur.

    Des fonctions prcompiles : getchar, putchar, scanf, printf, .... FILE est l'alias d'une structure dont l'utilisateur n'a pas besoin de connatre

    l'organisation. Ce type n'est jamais utilis en tant que tel, on utilise toujours le type FILE * que l'on

    appelle un flux. Les troix flux standard stdin, stdout, stderr sont automatiquement ouverts au lancement

    de tout programme. Ils sont connects par dfaut l'cran pour les sorties, au clavier

    Ils peuvent tre explicitement redirigs vers un fichier ou un priphrique.

    8.1. Les E/S formates : printf

    prototype : int printf(const char * format, identificateurs ....)

    printf convertit ses arguments d'aprs les spcifications de son format et crit lersultat dans le flot de sortie standard stdout.

    Elle retourne le nombre de caractres crits ou une valeur ngative en cas d'erreur.

    La chane de caractres format contient deux types d'informations : des caractresordinaires qui sont recopis sur le flot de sortie, et des spcifications de conversionsdont chacune provoque la conversion et l'impression des arguments suivants deprintf.

    Chaque spcification de conversion commence par % et se termine par un caractrede conversion. Entre les deux on peut placer dans l'ordre :

    des drapeaux qui modifient la spcification : - cadre l'argument gauche + imprime systmatiquement le signe du nombre espace : si le premier caractre n'est pas un signe, place un espace au

    0 : pour les conversion numriques, complte le dbut du champ pardes 0.

    Un nombre qui prcise la largeur minimum du champ d'impression. Un point qui spare la largeur du nombre de dcimales. Un nombre indiquant la prcision Une lettre h (short ou unsigned short), l (long ou unsigned long) ou L (long

    double) qui modifie la largeur du champ

    La largeur et la prcision peuvent tre donnes en paramtre printf en mettant * leur place. Les paramtres suivant le format seront alors convertis en entiers et

    Les spcifications de conversions sont :Type de l'argument

    d,i int ; notation dcimale signe

  • Langage C - Jacoboni - 16/02/98 -48

    o int ; notation octale non signex, X int ; notation hexadcimale non signeu int ; notation dcimale non signec int ; un seul caractre aprs conversion en unsigned chars char * ; les caractres sont imprims jusqu' \0f double ; notation dcimale de la forme [-]mmm.ddd la prcision par

    e, E double ; notation exponentielleg, G double ; l'impression se fait suivant le format %e si l'exposant est

    infrieur a -4 ou suprieur a la prcision, sinon %fp void * ; crit l'argument sous forme de pointeursn int * ; le nombre de caractres crits jusqu' prsent par cet appel

    printf est crit dans l'argument.% affiche un %

    8.2. Les E/S formates : scanf

    prototype : int scanf (const char * format, adresses ...)

    le format contient : des espaces ou des caractres de tabulations qui sont ignors des caractres ordinaires (diffrents de %), dont chacun est supp

    s'identifier au caractre suivant du flot d'entre. des spcifications de conversion du mme type que pour printf.

    8.3. Les E/S : les fichiers

    Il existe deux types de fonctions de manipulation de fichiers en C. Les fonctions de niveaux 1 Les fonctions de niveaux 2.

    Les fonctions de niveaux 1 sont des fonctions proches du systme d'exploitation quipermettent un accs direct aux informations car elles ne sont pas bufferises. Ellesmanipulent les informations sous forme binaire sans possibilits de formatage, et lefichier est identifi par un numro (de type entier) fix lors de l'ouverture du fichier.

    Les fonctions de niveaux 2 sont bases sur les fonctions de niveaux 1, elleseffectuent des E/S bufferises, permettent une manipulation binaire ou formate desinformations. Le fichier est identifi par un flux (FILE *) qui contient des informationslabores relatives au fichier : adresse du buffer, pointeur sur le buffer, numro dufichier pour les fonctions de niveaux 1, etc....

    8.4. E/S fichiers :Les fonctions de niveaux 1

    Ouverture d'un fichier : prototypeint open (char * nomfichier , int mode, int permissions)

    mode est une combinaison de O_CREAT : Le fichier est cr s'il n'existe pas O_RDONLY : Ouverture en lecture seule O_WRONLY : Ouverture en criture seule O_BINARY : Mode non translat (binaire) O_TEXT : Mode translat (ascii) O_RDWR : Ouverture en lecture/criture O_TRUNC : Si le fichier existe son contenu est dtruit.

  • Langage C - Jacoboni - 16/02/98 -49

    open renvoie un entier qui sera utilis pour accder au fichier par la suite. openrenvoie -1 en cas d'erreur.

    On considrera que permissions vaut toujours 0 (pour nous)

    Fermeture du fichier : close (int numrofichier)

    Ecriture dans le fichierint write (int num_fic, char *adre, int nombre_octets)

    lecture dans le fichierint read (int num_fic, char * adre_stock, int nombre_octets)read renvoie le nombre d'octets transfrs

    Fin de fichiereof (numro_fichier) renvoie -1 ds que la fin de fichier a t atteinte, 0 sinon.

    Accs directlseek (numro_fichier, dplacement, mode) mode peut prendre les valeurs 0, 1, 2 selon que le dplacement doit tre :

    0 : par rapport au dbut du fichier1 : par rapport la position courante2 : par rapport la fin du fichier.

    Exemple : recopier l'entre sur la sortie.#include void main(){ char tamp[BUFSIZ] ;

    int n;while ((n=read(stdin, tamp, BUFSIZ))>0)

    write(stdout, tamp, n);}

    8.5. E/S fichiers :Les fonctions de niveaux 2

    Ouverture d'un fichier : prototypeflux = FILE * fopen (char * nom_fic, char *mode) avec mode = "r", "w", "a", "a+", "r+", "w+"

    Fermeture d'un fichier : fclose (FILE * flux)

    Ecriture "brutale" :size_t fwrite (const void *ptr, size-t taille, size_t nobj, FILE * flux) ;

    Lecture "brutale" :size_t fread (void * ptr, size-t taille, size_t nobj, FILE * flux);

    Accs direct :int fseek (FILE *flux, long offset , int mode) mode peut prendre les valeurs 0, 1, 2 selon que le dplacement doit tre :

    0 : par rapport au dbut du fichier1 : par rapport la position courante2 : par rapport la fin du fichier.

    8.6. Les E/S formates

    fscanf (FILE * flux, const char * format , liste_adresses)

    scanf est construit avec fscanf

    fprintf(FILE * flux, const char * format , liste_expressions)

  • Langage C - Jacoboni - 16/02/98 -50

    printf est construit avec fprintf

    int fgetc (FILE * flux) => saisir un caractre dans le flux*

    en fait c=getchar() c=fgetc (stdin)

    int fputc (int c, FILE * flux) => crire un caractre dans le flux

    en fait putchar(c) fputc (stdin,c)

    char * fgets (char * chane, int lgmax, FILE * flux) : lire une chaine dans le flux.

    Cas particulier gets (char * chane)

    int fputs (char * chane, FILE *flux) : crire une chaine dans le flux.

    Cas particulier puts (char * chane)

    Autres fonctions d'E/S : int ungetc(int c, FILE * flux) remet c dans le flot int ftell (FILE * flux) donne la position courante dans le fichier ou -1 en cas

    d'erreur

  • Langage C - Jacoboni - 16/02/98 -51

    9. Neuvime partie : Complments

    9.1. Complments 1 : Le prprocesseur

    Le prprocesseur est un programme standard qui effectue des modifications sur untexte source. Ce texte source peut tre absolument n'importe quoi (du Pascal, duFortran, une recette de cuisine, ...), car c'est un outil standard Unix. C'estessentiellement en C qu'il est utilis.

    Le prprocesseur modifie le source d'aprs les directives donnes par leprogrammeur, et introduites par le caractre #. Ces directives peuvent apparatren'importe o dans le fichier, pas ncessairement au dbut.

    La directive du prprocesseur commence par un # et se termine par la fin de ligne. Sila directive ne tient pas sur une seule ligne, on peut l'crire sur plusieurs en terminantles premires lignes par \ qui annule le retour chariot.

    9.1.1. Premire utilisation : substitution de symboles Syntaxe: #define symbole chane Gnralement et pour plus de clart les symboles #-dfinis sont mis en majuscule (ce

    n'est pas obligatoire). Le symbole est remplac par la chane chaque fois qu'il est rencontr dans le source. La chaine considre commence au premier caractre non blanc aprs le symbole, et se

    termine sur le premier caractre non blanc en allant vers la gauche partir de la fin deligne.

    Avant la norme ansi le #define tait la seule faon de dfinir des constantes#define MAXTAB 100...int tab[MAXTAB];...if (i>MAXTAB)...

    La substitution de symbole permet aussi de modifier l'aspect d'un programme source :#define Loop for(;;){#define EndLoop }

    Ce qui peut donner :Loop

    i++if (...)

    break;...

    EndLoop Danger : Lisibilit du programme par les autres ???

    9.1.2. Deuxime utilisation : Macro-instructions Une dfinition de macro_instruction permet une substitution de texte paramtre par des

    arguments.#define symbole(a1,a2,....) chaine

    Il n'y a pas d'espace entre le symbole et ( Lors de l'appel, symbole(x,y,...) est remplac par la chane dans laquelle toutes les

    occurences des arguments formels a1, a2, sont remplaces par les arguments effectifsx, y, ...

    Exemple :#define MAX(a,b) ((a) > (b) ? (a) : (b))avec cette dfinition la ligne :x=MAX(58,x*y) sera remplace parx= ( (58) > (x*y) ? (58) : (x*y) )

  • Langage C - Jacoboni - 16/02/98 -52

    Si on ne met pas de parenthses sur les paramtres formels il peut y avoir des erreurs Par exemple :

    #define carre(a) (a*a)....x=carre(y+1) sera transform en x=(y+1*y+1) soitx=2*y+1 !!!

    9.1.3. Troisime utilisation : Inclusion de fichier Gnralement les fichiers inclure ont un nom qui se termine par .h (header) mais ce

    n'est pas obligatoire #include va chercher le fichier stdio.h dans le rpertoire spcial contenant

    les fichiers header et l'incorpore au source. #include "/user/dudule/monHeader.h" va chercher le fichier monHeader.h dans le

    rpertoire /user/dudule et l'incorpore au source.

    9.1.4. Quatrime utilisation : Compilation conditionnelle Il existe 3 formes de tests possibles : Forme 1 : Tester si une expression est nulle

    #if expressionlignes diverses#endif

    Si l'expression numrique constante est vraie (Non nulle) les lignes suivantes sonttraites par le prprocesseur sinon elles sont ignores jusqu'au #endif

    #define MAC 1...#if MAClignes diverses#endif...#if SUNlignes diverses#endif...#if TEKTRO || HPlignes diverses#endif...

    Formes 2 et 3 : Tester si un symbole a dj t dfini. Forme 2 : tester si un symbole est dfini

    #ifdef bidulelignes diverses#endif

    Forme 3 : Tester si un symbole n'est pas dfini#ifndef bidulelignes diverses#endif

    C'est souvent utilis pour viter qu'un fichier header soit #inclus plusieurs fois.Exemple : le fichier toto.h#ifndef _toto_#define _toto_lignes diverses#endif

  • Langage C - Jacoboni - 16/02/98 -53

    9.1.5. Le prprocesseur : Oprateur # L'oprateur # ne peut s'employer que dans la dfinition d'une macro. Il permet de

    remplacer un argument formel par un argument effectif transform automatiquement en

    Exemples :#define str(s) #s le prprocesseur remplacera alorsprintf(str(bonjour)) par printf("bonjour")

    Si on avait fait #define str(s) "s",on aurait obtenu printf("s") !!

    #define ipr(x) printf(#x "=%d", x)Le prprocesseur remplace alors ipr(i); parprintf("i" "=%d",i); ce qui donne aprs concatnationprintf("i=%d", i);

    9.1.6. Le prprocesseur : Oprateur ## Cet oprateur ne peut s'employer que dans un #define (macro ou substitution de

    symbole). Lorsque deux lments sont spars par ## ils sont concatns pour former un nouveau

    symbole Exemple :

    #define JACOBONI tresfort#define colle(a,b) a##bcolle(JACO,BONI) donnera JACOBONI puis tresfort !

    Exemple plus intressant :#define trace(s,t) printf("x"#s"=%d, x"#t"=%s",x##s,x##t)trace(1,2); sera transform enprintf("x1=%d, x2=%s", x1,x2);

    9.1.7. Exemple de fichier Header : def.h#ifndef _def_#define _def_#include #include #include /**********************************************

    Amlioration malloc et calloc :Permet d'crire

    int *p;p=Malloc(int) au lieu dep=(int *) malloc (sizeof(int))

    idem pour calloc**********************************************/#define Malloc(type) (type *)malloc(sizeof(type))#define Calloc(n,type)(type *)calloc(n,sizeof(type))

    /**********************************************Amlioration de la dclaration de structure

    structDEF (arbrebinint) {arbrebinint *fg;int valeur ;arbrebinint *fd;

  • Langage C - Jacoboni - 16/02/98 -54

    };au lieu de

    struct ARBREBININT;typedef struct ARBREBININT arbrebinint;struct ARBREBININT {

    arbrebinint *fg;int valeur ;arbrebinint *fd;

    };**********************************************/#define structdecl(type) struct _##type;\

    typedef struct _##type type#define structdef(type)struct _##type#define structDEF(type)structdecl(type);structdef(type)/*********************************************/typedef enum { false, true} bool;#endif

    9.2. Complments 2 : Arguments de la ligne de commande Il est possible en C de rcuprer les arguments passs sur la ligne de commande.

    Quand on appelle la fonction main, celle-ci reoit trois paramtres : Le premier est un entier qui reprsente le nombre d'arguments prsents sur la ligne de

    commande. On l'appelle gnralement argc. Le second est un pointeur vers un tableau de chanes de caractres qui contiennent les

    arguments proprement dits. On l'appelle gnralement argv. Exemple : soit le programme echo qui ne fait qu'afficher ses arguments.

    echo Bonjour Matre Jacoboniargv[0] argv[1] argv[2] argv[3]et argc vaut 4.

    #include int main(int argc, char *argv[]){

    while (--argc>0)printf("%s%s", *++argv, (argc>1) ? " " : "");

    /* ou printf( (argc>1) ? "%s " : "%s", *++argv); */printf("\n");return 0;

    } Par convention, argv[0] est le nom du programme excutable et donc argc vaut au moins

    1.

  • Langage C - Jacoboni - 16/02/98 -55

    10. Dixime partie : Types de Donnes abstraits

    10.1. Les types de donnes abstraits

    10.1.1. dfinition 1 : un ensemble de donnes et d'oprations sur ces donnes

    10.1.2. dfinition 2 : un ensemble de donnes organis de sorte que les spcifications des objets et

    des oprations sur ces objets soient spares de la reprsentation interne desobjets de de la mise en oeuvre des oprations

    ns de proccupation de gnie logiciel abstraction encapsulation vrification de types

    exemples : le type entier muni des oprations + - % / < > = >= =< est un TDA

    une pile muni des oprations initialiser, empiler, dpiler, consulter lesommet de pile est un TDA

    les TDA gnralisent les types prdfinis.

    10.1.3. Dfinition 3 : Incarnation d'un TDA une incarnation (une ralisation, une mise en uvre) d'un TDA est la structure

    de donnes particulire et la dfinition des oprations primitives dans unlangage particulier

    on parle aussi de type de donnes concret remarque : dfinir le jeu de primitives peut s'avrer un problme dlicat dlicat exemple : on peut mettre en uvre le TDA pile en utilisant en mmoire des

    cellules contigus (tableau) ou des cellules chanes programmation l'aide des TDA:

    les programmeurs ont deux casquettes le concepteur du TDA qui met en uvre les primitives et doitconnatre la reprsentation interne adopte l'utilisateur du TDA qui ne connat que les services (lesoprations) et n'accdent jamais la reprsentation interne

    10.1.4. Avantages des TDA criture de programmes en couches :

    la couche suprieure dans les termes du domaine de problmes non avec les dtails du langage de programmation

    sparation claire des offres de service et du codage facilit de comprhension et d'utilisation prise en compte de types complexes briques d'une structuration modulaire rigoureuse

    10.1.5. Inconvnients des TDA l'utilisateur d'un TDA connat les services mais ne connat pas leur cot le concepteur du TDA connat le cot des services mais ne connat pas leurs

    conditions d'utilisation le choix des primitives est quelque fois difficile faire

  • Langage C - Jacoboni - 16/02/98 -56

    10.2. Le TDA Liste

    10.2.1. dfinitions : une liste est une suite finie (ventuellement vide) d'lments liste homogne : tous les lments sont du mme type liste htrogne : les lments sont de type diffrents

    10.2.2. Hypothses dans la suite nous interessons aux listes homognes tous les lments appartiennent un TDA ELEMENT qui possde un lment

    vide et sur lequel on peut : tester si deux lments sont identiques (prdicat ElementIdentique) affecter dans un lment un autre lment (ElementAffecter) saisir un lment (ElementSaisir) afficher un lment (ElementAfficher)

    on dispose d'un TDA POSITION permettant de reprer un lment dans la listesur lequel on peut :

    tester si deux positions sont gales (PositionIdentique) affecter dans une positi