Академический Документы
Профессиональный Документы
Культура Документы
2. Structure do -While .................................................................................................. 24 3. Structure for ............................................................................................................... 25 Chapitre 7 Les pointeurs .......................................................................................................... 27 1. Introduction ...................................................................................................................... 27 2. Adresse et valeur dune variable : .................................................................................... 27 3. Notion de pointeur :.......................................................................................................... 28 4. Arithmtique des pointeurs : ............................................................................................ 28 5. Allocation dynamique ...................................................................................................... 29 Chapitre 8 Les tableaux ............................................................................................................ 32 1. Les tableaux une dimension .......................................................................................... 32 1.1. Dclaration et mmorisation ..................................................................................... 32 1.2. Initialisation et rservation automatique ................................................................... 32 1.3. Accs aux composantes ............................................................................................. 33 1.4. Affichage et affectation ............................................................................................. 33 2. Les tableaux deux dimension ........................................................................................ 34 2.1. Dclaration et mmorisation ..................................................................................... 34 2.2. Accs aux composantes ............................................................................................. 35 2.3. Affichage et affectation ............................................................................................. 35 3. Pointeurs et tableaux : ...................................................................................................... 36 4. Tableau de pointeurs : ...................................................................................................... 36 Chapitre 9 LES FONCTIONS.................................................................................................. 38 1. Dfinition de fonctions ..................................................................................................... 38 2. Passage des paramtres par valeur ................................................................................... 39 3. Passage de l'adresse d'une variable ( eq. passage par variable) ........................................ 39 4. Passage de l'adresse d'un tableau une dimension .......................................................... 40 5. Passage de l'adresse d'un tableau deux dimensions ....................................................... 41 Chapitre 10 Les types de variables complexes ......................................................................... 42 1. Notion de structure ........................................................................................................... 42 2. Dclaration de structure : ................................................................................................. 42 3. Accs aux membres dune structure : .............................................................................. 43 4. Initialisation dune structure : .......................................................................................... 43 5. Affectation de structures : ................................................................................................ 43 6. Comparaison de structures : ............................................................................................. 43 7. Tableau de structures : ...................................................................................................... 44 8. Composition de structures : .............................................................................................. 44 9. Pointeur et structures : ...................................................................................................... 44 10. Les numrations : ......................................................................................................... 44 11. Les unions : .................................................................................................................... 45 11.1. Utilisation des unions .............................................................................................. 45
(A).
En Pascal
Langage C vers I #include <stdio.h> #define PI 3.14 float f_surface(float rayon) {float s; s=rayon*rayon*PI; return(s); }
Langage C vers II #include <stdio.h> #define PI 3.14 float f_surface(float); void main() { float surface; surface=f_surface(2.0); printf("%f\n",surface); } float f_surface(float rayon) {float s; s=rayon*rayon*PI; return(s); }
Program surface_cercle ; Const PI = 3.14 ; Function f_surface (rayon : real) : real ; Var s : real; Begin s:= rayon*rayon*PI; f_surface :=s; End ; Var surface : real ; Begin Surface:=f_surface(2.0); writeln(surface); end;
3. Les identificateurs
Un identificateur est une suite de caractres parmi les lettres (minuscules ou majuscules, mais non accentues), les chiffres, le tirait bas. (exemple : compte, Note_1, _indice) Le premier caractre d'un identificateur ne peut pas tre un chiffre. Les majuscules et minuscules sont diffrencies. Le compilateur peut tronquer les identificateurs au-del d'une certaine longueur. Cette limite dpend des implmentations, mais elle est toujours suprieure 31 caractres.
4. Les mots-clefs
Un certain nombre de mots, appels mots-clefs, sont rservs pour le langage lui-mme et ne peuvent pas tre utiliss comme identificateurs. L'ANSI-C compte 32 mots clefs :
auto const double float int short struct unsigned break continue else for long signed switch void case default enum goto register sizeof typedef volatile char do extern if return static union while
Ces mots peuvent tre rangs en catgories : Tableau 2.2 : mots-clefs du langage C les spcificateurs de stockage auto register static extern typedef les spcificateurs de type char double enum float int long short signed struct union unsigned void les qualificateurs de type const volatile les instructions de contrle break case continue default do else for goto if switch while Divers return sizeof
5. Les commentaires
Un commentaire dbute par /* et se termine par */. Par exemple, /* Ceci est un commentaire */ On ne peut pas imbriquer des commentaires. // nous permet dcrire un commentaire sur une mme ligne
6. Les constantes
Une constante est une valeur qui apparat littralement dans le code source d'un programme, le type de la constante tant dtermin par la faon dont la constante est crite. Les constantes vont tre utilises, par exemple, pour linitialisation de variables. 6.1. Les constantes entires Une constante entire peut tre reprsente de 3 manires diffrentes suivant la base dans laquelle elle est crite : dcimale : par exemple, 0 et 2437 sont des constantes entires dcimales. octale : la reprsentation octale d'un entier correspond sa dcomposition en base 8. Les constantes octales doivent commencer par un zro. Par exemple, les reprsentations octales des entiers 0 et 255 sont respectivement 00 et 0377. hexadcimale : la reprsentation hexadcimale d'un entier correspond sa dcomposition en base 16. Les lettres de a/A f/F sont utilises pour reprsenter les nombres de 10 15. Les constantes hexadcimales doivent commencer par 0x ou 0X. Par exemple, les reprsentations hexadcimales de 14 et 255 sont respectivement 0xe et 0xff. Remarque : On peut spcifier explicitement le format d'une constante entire en la suffixant par u ou U pour indiquer qu'elle est non signe, ou en la suffixant par l ou L pour indiquer qu'elle est de type long. Par exemple : Tableau 2.3 : exemples de constantes entires Constante type 1234 Int 02154 Int 0x4d2 Int 123456789L Long 1234U Unsigned int 124687564UL Unsigned long int
Exemples : int Nb_lignes ; /* dclaration dune variable de type entier */ Nb_lignes = 15 ; /* initialisation de cette variable 15 */ #define TEL 75410452 const annee = 2002 ; /* affecte une valeur une variable, cette valeur ne pourra plus tre chang par la suite */ 6.2. Les constantes relles Ils sont de lune des deux formes suivantes : En notation dcimale : [+-]m.n ou m et n sont des entiers. Exemple : 2.5 -123.47 . En notation scientifique (mantisse et exposant) : [+-]m.n [e/E][+-]p ou m,n et p sont des entiers. Exemple : -14.5 e-2 (-14.5 10-2) Par dfaut, une constante relle est reprsente avec le format du type double. On peut cependant influer sur la reprsentation interne de la constante en lui ajoutant un des suffixes f/F ou l/L. Les suffixes f et F forcent la reprsentation de la constante sous forme d'un float, Les suffixes l et L forcent la reprsentation sous forme d'un long double. Tableau 2.4 : Exemples de constantes relles constante type 12.34 Double 12.3 e-4 Double 12.34L Long double 12.34F Float 6.3. Les constantes caractres Elles sont sous une des formes suivantes : x dsigne le caractre imprimable x ( Sauf lapostrophe et lantislash et les guillemets) \nnn dsigne le caractre de code octal nnn (nnn est un nombre dans la base 8) \\ dsigne le caractre \ (ou encore \134 en ASCII) \ dsigne le caractre (ou encore \47 en ASCII) \ " dsigne le caractre " \n dsigne le caractre <newline> nouvelle ligne 6.4. Les constantes chanes de caractres Une constante chane de caractres est une suite de caractres entours par des guillemets. Par exemple,''Ceci est une chane de caractres'' (ATTENTION : en pascal une chane est entoure par deux apostrophes ceci est une chane en pascal). Elle peut contenir des caractres non imprimables, dsigns par les reprsentations vues prcdemment. Par exemple, ''ligne 1 \n ligne 2'' A l'intrieur d'une chane de caractres, le caractre '' doit tre dsign par \''. Enfin, le caractre \ suivi d'un passage la ligne est ignor. Cela permet de faire tenir de longues chanes de caractres sur plusieurs lignes. Par exemple : Sans espace ''ceci est une longue longue longue longue longue longue longue longue \ chane de caractres'' Remarque : Le compilateur ajoute \0 la fin de la chane dans la mmoire.
Il faut savoir distinguer la constante caractre de la constante chane de caractre. Ainsi x et "x" ne sont pas quivalents. Le premier reprsente la valeur numrique du caractre x, le second est une chane ne comprenant quun caractre (la lettre x) en plus \0 final.
8. Dclaration de variables
Les variables doivent toutes tre dclares avant dtre utilises. A une variable correspond un espace en mmoire et un mcanisme permettant dadresser cet emplacement. En C une variable est caractris par : Son nom (un identificateur) Son type (type de base ou type dfinie par lutilisateur) Une dclaration de variables a la forme : type liste de variables initialises ou non; Exemples : int var_globale1=0, var_globale2; float var ; int i,j,k ; char backslash=\\ ; int i=0 ; float eps=1.0 e-5 ;
9. Dclaration de constantes
Les constantes doivent toutes tre dclares et initialises avant dtre utilises. Il existe 2 mthodes pour la dclaration des constantes. Mthode 1 : #define nom_cste valeur /* Sans point virgule la fin */ Exemple : #define PI 3.14
Le compilateur ne rserve pas de place en mmoire. Les constantes dclares par #define s'crivent traditionnellement en majuscules, mais ce n'est pas une obligation. Mthode 2 : const type nom_cste = valeur ; Exemple : const float PI = 3.14 ; Dans ce cas, le compilateur rserve de la place en mmoire (ici 4 octets), pour la variable PI, mais dont on ne peut changer la valeur. Remarques gnrales 1- Le type Boolen nexiste pas dans le langage C 2- Il ny a pas de notion de procdure en langage C (On peut dire que une procdure en langage C est une fonction sans rsultats void nom_procedure(paramtres) ) 3- Le langage C ne permet pas de dclarer des fonctions lintrieur dautres fonctions
10
o Par contre, il dlivrera une valeur flottante ds que lun des oprandes est un flottant. Par exemple : float x; x = 3 / 2; affecte x la valeur 1. Par contre x = 3 / 2.0; /* affecte x la valeur 1.5. */ L'oprateur % ne s'applique qu des oprandes de type entier. Notons enfin quil n'y a pas en C doprateur effectuant llvation la puissance. De faon gnrale, il faut utiliser la fonction pow(x,y) de la librairie math.h pour calculer xy
ne pas confondre l'oprateur de test dgalit == avec loprateur daffection =. Ainsi, le programme main() { int a = 0, b=1,c; c= (a==b) ; } c contient la valeur 0 car a est diffrent b donc lvaluation de lexpression (a = = b) donne la valeur boolenne Faux qui correspond la valeur 0 en C
Attention !!!!
Comme pour les oprateurs de comparaison, la valeur retourne par ces oprateurs est un int qui vaut 0 si la condition est faux.
11
Dans une expression de type : expression1 op1 expression2 op2 ...expressionN , lvaluation se fait de gauche droite et s'arrte ds que le rsultat final est dtermin. Par exemple dans int i=18,j=0; if ((i >= 0) && (i <= 9) && !(j == 0)) La dernire expression !(j == 0) ne sera pas value si i n'est pas entre 0 et 9.
7. L'oprateur virgule
Une expression peut tre constitue d'une suite d'expressions spares par des virgules : expression1, expression2, ..., expressionN Cette expression est alors value de gauche droite. Sa valeur sera la valeur de l'expression de droite. Par exemple, le programme main() { int a, b; b = ((a = 3), (a + 2)); // printf(''\n b = %d \n'',b); }
a=3 ; b=a+2 ;
La valeur de b est 5 Autre exemple : int i, j ; j=2; j=j+1; i=j; j=j+1; i=(j=2, j++, j++);
i = 3 et j = 4
12
La virgule sparant les arguments d'une fonction ou les dclarations de variables ne reprsente pas l'oprateur virgule.
13
14
BS
15
Plus gnralement, les valeurs maximales et minimales des diffrents types entiers sont dfinies dans la librairie standard limits.h. Le mot-clef sizeof a pour syntaxe sizeof(expression) o expression est un type ou une variable. Le rsultat est un entier gal au nombre d'octets ncessaires pour stocker le type ou la variable. Par exemple : unsigned short x; taille = sizeof(unsigned short); taille = sizeof(x); Dans les deux cas, taille vaut 2.
Tableau 4.1 : les types flottant selon larchitecture En C Float Double Long double PC Intel 32 bits 64 bits 128 bits En Algo flottant Flottant double prcision Flottant quadruple prcision
16
BSM
Dans la base 2 : x = (-1)S 1,M 2E Avec : s : bit de signe de la mantisse M : la mantisse E : exposant rel = (exposant biais dans la base10 127) Rq : de mme le double : E biais sur 11 bits et la Mantisse sur 52 bits et un BSM
On trouve aussi un constructeur de type par numration : enum <identificateur> { liste de valeurs symboliques } Exemple :
0 1 2 3 4
enum couleur { noir, bleu , vert , rouge, jaune } q1,q2 ; Dfinit le type par numration nomm couleur et dclare deux variables q1 et q2 de ce type. (exemple : q1=rouge ; q2=jaune ; ..).
17
18
Remarque: On peut placer la longueur de la variable entre le signe % et la lettre spcificateur. Par exemple %3d indique quon va lire un entier de 3 chiffres et le reste des chiffres sont ignors. scanf ("%3d",&i) ; Si lon spare les spcificateurs de format par des espaces ou par des virgules alors les valeurs lire seront spares par les mmes sparateurs. Exemple 2: char alpha; scanf("%d",&alpha); Si l'utilisateur saisie 97 tout va bien, alpha devient le caractre dont le code ASCII vaut 97 qui est a. Si l'utilisateur saisie a, sa saisie est ignore (PB !!!). Exemple 3: (***) Tout caractre ou nombre saisi au clavier et non pris en compte par la fonction scanf est rang dans le tampon dentr qui est de type FIFO (First In First Out). #include <stdio.h> void main() { char c1,c2; printf("ENTRER UN CARACTERE: "); scanf("%c",&c1); printf("VOICI SON CODE ASCII EN HEXADECIMAL: %x\n",c1); printf("ENTRER UN AUTRE CARACTERE: "); scanf("%c",&c2); printf("VOICI SON CODE ASCII EN HEXADECIMAL: %x\n",c2); } Excution (trace) : Si l'utilisateur saisit K pour c1, le programme donnera l'cran d'excution suivant:
lutilisateur saisi K puis il a appuy sur RETURN donc on a dans le tampon le caractre LF qui a le code ASCII en hxa a : le tampon LF FIFO VOICI SON CODE ASCII EN HEXADECIMAL: 4b ENTRER UN AUTRE CARACTERE: VOICI SON CODE ASCII EN HEXADECIMAL: a ENTRER UN CARACTERE: K
Le deuxime scanf reoit la valeur du tampon qui contient le caractre retour la ligne LF qui est un caractre non imprimable et de code ASCII a La solution : En TURBOC la fonction flushall() permet de vider le tampon d'entre. En l'invoquant aprs un appel scanf, on se dbarrasse des problmes de flux d'entre. 2.2. La fonction gets stdio.h Elle affecte une chane de caractre lue dans le flux en entre stdin dans s. Sa dclaration est la suivante : Char * gets (char * s) ; Lorsquon lit une chane de caractres avec scanf, la lecture sarrte ds la rencontre dun blanc. Avec la fonction gets, la lecture se termine la rception dun retour chariot \n.
19
Exemple : #include <stdio.h> void main() { char * CH; gets(CH); } 2.3. La fonction getchar() stdio.h La fonction getchar permet la saisie d'un caractre (char). Elle appartient la bibliothque stdio.h. Les 2 critures suivantes sont quivalentes: char c; printf("ENTRER UN CARACTERE: "); scanf("%c",&c); char c; printf("ENTRER UN CARACTERE: "); c = getchar();
Non formate, la fonction getchar est moins gourmande en place mmoire que scanf. Il vaut mieux l'utiliser quand cela est possible; getchar utilise le flux d'entre exactement comme scanf. Autre fonction qui permet de saisir un seul caractre : int getch() ; de la bibliothque conio.h . Cette fonction ne demande pas une validation par la touche entre pour rcuprer le caractre saisi. Exemple : c = getch() ; Nous pouvons utiliser cette fonction sans rcupration du caractre saisi : Exemple : getch () ;
20
Remarque: 1. printf ("%kd",n) ; Affiche au moins k caractres droite. Exp1 : k=3 et n = 25 affiche _25 (tir bas remplace lespace) Exp2 : k=2 et n = 355 affiche 355 2. printf ("%-kd",n) ; Affiche au moins k caractres gauche. Exp1 : k=3 et n = 25 affiche 25_ (tir bas remplace lespace) Exp2 : k=2 et n = 355 affiche 355 Affiche le nombre rel en dcimal avec 6 chiffre aprs la virgule, par dfaut. Exp1 : x=1.5 1.500000 4. printf ("%kf",x) ; Affiche le nombre rel en dcimal avec 6 chiffre aprs la virgule, par dfaut. Avec k reprsente la longueur minimale du nombre. Exp1 : k=9, x=1.5 _ _1.500000 5. printf ("%kf.J",x) ; Affiche le nombre rel en dcimal avec 6 chiffre aprs la virgule, par dfaut. Avec k reprsente la longueur minimale du nombre et J reprsente le nombre de chiffre aprs la virgule. Exp1 : k=9, J=3 ,x=1.5 _ _ _ _ _1.500 3. printf ("%f",x) ; 3.2. La fonction puts Envoie une chane de caractres vers stdout et ajoute un saut de ligne (newline). int puts (const char * s) ; Exemple : puts ( ceci est un exemple ); 3.3. La fonction putchar Envoie un caractre vers stdout (cran) int putchar (int c) ; Exemple : char c ; c= A putchar (c); putchar (B);
21
Remarques : o Les { } ne sont pas ncessaires lorsque les blocs ne comportent qu'une seule instruction. o On peut avoir des if imbriqus Exemples : if (a > b) max = a; else max = b; if (A-B) printf("A est diffrent de B\n"); else printf("A est gal B\n"); int a,b,c; ; if (!a) //quivalent if (a==0) { printf( cas o a = = 0 ); ; } else // commentaire : cette partie traite le cas o a != 0 { 21
2. Instruction switch
Cest un moyen qui permet des choix multiples uniquement sur des entiers ou des caractres. Pascal case choix of cst1 : begin liste d'instructions 1 ; end cst2 : begin liste d'instructions 1 ; end . else : begin liste instructions N ; end end; Langage C switch (choix) { case cst1 : liste d'instructions 1 ; break; case cst2 : liste d'instructions 1 ; break; . default : liste instructions N ;
}
Remarques : o choix doit tre de type char ou int o Le bloc else nest pas obligatoire. o choix, cst1, cst2 et les autres valeurs o Begin et end ne sont pas obligatoire en sont de mme type cas dune seule instruction Linstruction break permet de sortir de linstruction switch. Elle est importante car si on ne la met pas aprs chaque cas dexcution alors toutes les instructions aprs ce cas seront excutes (bien sur sils ne sont pas suivis dune autre instruction break). Exemple : int mois ; scanf(" %d" ,&mois) ; switch ( mois ) { case 1 : printf(" janvier" ) ; break ; case 2 : printf(" fevrier" ) ; break ; case 12 :printf(" dcembre" ); break ; default : printf(erreur) }
22
Exemple 1: /* Afficher les nombres de 0 9 */ int I = 0; while (I<10) { printf("%d \n", I); I++; } /* Afficher les nombres de 0 9 */ int I = 0 ; while (I<10)
23
printf(%d\n,I++); /* Afficher les nombres de 1 10 */ int I = 0 ; while (I<10) printf(%d\n,++I); Exemple2: /* faire la somme des N premiers terme entier*/ int somme=0, i = 0; while (i<N) { somme += i; i++ ; } Exemple3: /* Afficher des caractres */ unsigned char c=0; while (c<255) printf("%c \n", c++);
2. Structure do -While
Pascal Repeat bloc dinstruction ; until (expression) do { bloc dinstructions; } while ( expression ); - Le bloc d'instructions est excut au moins une fois et jusqu ce que l'expression fournit une valeur gale zro (eq false). - Les { } ne sont pas obligatoires, si le bloc dinstruction contient une seule instruction. Langage C
Invers
- Le bloc d'instructions est excut au moins une fois et jusqu ce que l'expression fournit une valeur vrai.
do - while est comparable la structure Repeat du langage Pascal si la condition finale est inverse logiquement.
24
La structure do - while est semblable la structure while, avec la diffrence suivante : while value la condition avant d'excuter le bloc d'instructions. do - while value la condition aprs avoir excut le bloc d'instructions. Ainsi le bloc d'instructions est excut au moins une fois. Une application typique de do - while est la saisie de donnes qui doivent remplir une certaine condition. Exemple1: Lecture dun nombre rel dans lintervalle [1 , 10] float N; do { printf("Introduisez un nombre entre 1 et 10 :"); scanf("%f", &N); } while (N<1 || N>10); Exemple2 : division de deux entiers (diviseur doit tre diffrent de zro) int n, div; printf("Entrez le nombre diviser : "); scanf("%d", &n); do { printf("Entrez le diviseur ( != 0) : "); scanf("%d", &div); } while (!div); //while (div==0) printf("%d / %d = %f\n", n, div, (float)n/div);
Exemple3 : Lecture dun nombre rel positif float N; do { printf("Entrer un nombre (>= 0) : "); scanf("%f", &N) } while (N < 0); printf("La racine carre de %.2f est %.2f\n", N, sqrt(N));
3. Structure for
La structure pour en langage algorithmique est utilises pour faciliter la programmation de boucles de comptage. La structure for en C est plus gnrale et beaucoup plus puissante.
25
for ( expr1 ; expr2 ; expr3 ) { bloc d'instructions ; } Est quivalente : expr1; while (expr2 ) { bloc d'instructions expr3 ; } expr1 est value une fois avant le passage de la boucle. Elle est utilise pour initialiser les donnes de la boucle. expr2 est value avant chaque passage de la boucle. Elle est utilise pour dcider si la boucle est rpte ou non. expr3 est value la fin de chaque passage de la boucle. Elle est utilise pour rinitialiser les donnes de la boucle. En pratique, les parties expr1 et expr2 contiennent souvent plusieurs initialisations ou rinitialisations, spares par des virgules. Exemple1: /* affichage des carrs des nombres entiers compris entre 0 et 20 */ int I; for (I=0 ; I<=20 ; I++) printf("Le carr de %d est %d \n", I, I*I); /* Autre version : nest pas lisible */ int I; for (I=0 ; I<=20 ; printf("Le carr de %d est %d \n", I, I*I), I++) ; Exemple2 : Somme des nombres de 1 100 int n, tot; for (tot=0, n=1 ; n<101 ; n++) tot+=n; printf("La somme des nombres de 1 100 est %d\n", tot);
26
Adressage indirect: Accs au contenu d'une variable, en passant par un pointeur qui contient l'adresse de la variable. Exemple : Soit A une variable contenant la valeur 10 et P un pointeur qui contient l'adresse de A. En mmoire, A et P peuvent se prsenter comme suit: int a, P ; P = &a ; val(a) gale val(*P)
Adresses (F1)16 (F2)16 0000000000001010 0000000000000000 *P 0000000011110001 .. Variable P Variable A Mmoire centrale
27
3. Notion de pointeur :
Un pointeur est une variable dont la valeur est gale ladresse dun autre objet. On dclare un pointeur par linstruction suivante : Type * nom_du_pointeur ; Type de lobjet point En Pascal : nom_du_pointeur : ^Type ; Exemple :
(*En Langage Pascal*) pc : ^char ; (*pc est un pointeur pointant sur une variable de type char*) pi : ^integer ; (*pi est un pointeur pointant sur une variable de type int*) pf : ^real; (*pf est un pointeur pointant sur une variable de type float*)
// En Langage C char * pc; /*pc est un pointeur pointant sur un objet de type char*/ int *pi; /*pi est un pointeur pointant sur un objet de type int*/ float *pf; /*pf est un pointeur pointant sur un objet de type float*/
Loprateur unaire dindirection * permet daccder directement la valeur de lobjet point. Ainsi si p est un pointeur vers un entier i, *p dsigne la valeur de i. Par exemple, le programme :
void main() { int i =3; int * p ; /* p est un pointeur sur une variable de type entier */ p=&i; /* p contient ladresse de la variable i */ printf (\n contenu de la case mmoire point par p est : %d , *p) ; *p=5; /* p contient ladresse de la variable i */ printf (\n I = %d et *p = %d ,i, *p) ; }
Imprime : contenu de la case mmoire point par p est : 3 i = 5 et *p = 5 Dans ce programme, les objets i et *p sont identiques. Ils ont mme adresse et valeur. Cela signifie en particulier que toute modification de *p modifie i.
28
Si k est un entier et p est un pointeur sur un objet de type type. Lexpression p + k dsigne un pointeur sur un objet de type type dont la valeur est gale la valeur de p incrmente de k*sizeof(type). Il en va de mme pour la soustraction dun entier un pointeur et pour les oprateurs dincrmentation et de dcrmentation ++ et --. Exemple : (Soit : sizeof(int)=4 octets, mots mmoire=2octets et i est rang ladresse F1 dans la base 16).
Void main() { int i = 3 ; int *p1, *p2 ; /* p1 et p2 sont deux pointeur vers deux objets de type int */ p1 = &i ; /* p1 contient ladresse de lentier I */ p2 = p1 + 2; /* p2 contient la valeur rang dans p1 incrment de 2* sizeof (int) */ printf ( p1 = %x et p2 = %x , p1,p2) ; /*imprime p1= F1 et p2 = */ }
Remarque : Les oprateurs de comparaison sont galement applicables aux pointeurs condition de comparer des pointeurs qui pointent vers des objets de mme type. (exemple : int *p, *q ; if(q>p) { } )
5. Allocation dynamique
Lorsque l'on dclare une variable char, int, float .... Un nombre de cases mmoire bien dfini est rserv pour cette variable. Il n'en est pas de mme avec les pointeurs. Avant de manipuler un pointeur, il faut linitialiser soit par une allocation dynamique soit par une affectation dadresse p=&i. Sinon, par dfaut la valeur du pointeur est gale une constante symbolique note NULL dfinie dans stdio.h En gnral, cette constante vaut 0. On peut initialiser un pointeur p par une affectation sur p. Mais il faut dabord rserver p un espace mmoire de taille adquate. Ladresse de cet espace mmoire sera la valeur de p. Cette opration consistant rserver un espace mmoire pour stocker lobjet point sappelle allocation dynamique. Elle se fait en C par la fonction malloc de la librairie standard stdlib.h Sa syntaxe est la suivante : char* malloc (nbr_octets) Cette fonction retourne un pointeur de type char* pointant vers un objet de taille nbr_octets. Pour initialiser des pointeurs vers des objets qui ne sont pas de type char*, il faut convertir le type de la sortie de la fonction malloc laide dun cast.
29
Imprime : La valeur de p avant initialisation est : 0 La valeur de p aprs initialisation est : ff11 La valeur de *p est : 2 Analyse de lexemple : Avant lallocation dynamique, *p na aucun sens et toute manipulation de *p gnrerait lerreur suivante : segmentation fault. Lallocation dynamique a pour rsultat dattribuer une valeur p et de rserver cette adresse un espace mmoire compos de 4 octets pour stocker la valeur de *p. Remarque1 : Dans le programme :
#include <stdio.h> main() { int i ; int * p ; p=&i ; }
i et *p sont identiques et on na pas besoin dallocation dynamique puisque lespace mmoire ladresse &i est dj rserv pour un entier. Remarque 2 : La fonction calloc de la librairie stdlib.h a le mme rle que la fonction malloc mais elle initialise en plus lobjet point *p 0. Sa syntaxe est la suivante : calloc( nb_objets, taille_objet_octets)
30
Exemple :
Int n=10; Int *p ; p= (int*) calloc (n, sizeof(int)); /* tableau de n entiers*/
Est quivalent :
Int n=10; Int *p ; p= (int*) malloc (n * sizeof(int)); /* tableau de n entiers*/ For (i=0; i<n; i++) *(p+i)=0;
Enfin, lorsque lon na plus besoin de lespace mmoire alloue dynamiquement c'est--dire quand on nutilise plus le pointeur p, il faut librer cette place en mmoire. Ceci se fait laide de linstruction free qui a pour syntaxe : free( nom_du_pointeur) ; Libration de la mmoire : la fonction free
pi = (int*)malloc(16); /* on rserve 16 octets en mmoire : la place pour 4 entiers */ pr = (float*)malloc(24); /* on rserve 24 octets en mmoire : la place pour 6 rels */ . free(pi); /* on libre la place prcdemment rserve pour pi */ free(pr); /* on libre la place prcdemment rserve pour pr */
Remarque : *p++ quivalente *(p++) ++*p quivalente ++(*p) *++p quivalente *(++p)
31
Dclaration de tableaux en langage Pascal : NomTableau : array [Binf..Bsup] of TypeElem ; Dclaration de tableaux en C : TypeSimple NomTableau [nombreCases] ; Les noms des tableaux sont des identificateurs. Exemples : int notes [8] ; /* dclaration dun tableau nomm notes, de type int et de dimension 8 */ char tab [100] ; /* dclaration dun tableaux nomm tab, de type char et de dimension 100 */ float moy[40] ; /* dclaration dun tableau nomm moy, de type float et de dimention 100 */
Mmorisation
En C, le nom d'un tableau est le reprsentant de l'adresse du premier lment du tableau. Les adresses des autres composantes sont calcules (automatiquement) relativement cette adresse. Exemple: char A[5] = {A, 66, 70, C, 240}; 65 66 70 67 240
Si un tableau est form de N composantes et si une composante a besoin de M octets en mmoire, alors le tableau occupera de N*M octets. 1.2. Initialisation et rservation automatique Lors de la dclaration d'un tableau, on peut initialiser les composantes du tableau, en indiquant la liste des valeurs respectives entre accolades. Exemples : int A[5] = {10, 20, 30, 40, 50}; float B[4] = {-1.05, 3.33, 87e-5, -12.3E4}; int C[10] = {1, 0, 0, 1, 1};
32
Il faut videmment veiller ce que le nombre de valeurs dans la liste corresponde la dimension du tableau. Si la liste ne contient pas assez de valeurs pour toutes les composantes, les composantes restantes sont initialises par zro. Si la dimension n'est pas indique explicitement lors de l'initialisation, alors l'ordinateur rserve automatiquement le nombre d'octets ncessaires. Exemples int A[] = {10, 20, 30, 40, 50}; ==> Rservation de 5*sizeof(int) octets float B[] = {-1.05, 3.33, 87e-5, -12.3E4};
==> Rservation de 4*sizeof(float) octets
1.3. Accs aux composantes En dclarant un tableau par int A[5]; nous avons dfini un tableau A avec cinq composantes, auxquelles on peut accder par: A[0], A[1], ... , A[4] Exemple :
1.4. Affichage et affectation La structure for se prte particulirement bien au travail avec les tableaux. La plupart des applications se laissent implmenter par simple modification des exemples-types de l'affichage et de l'affectation.
Affichage du contenu d'un tableau : exemple
int A[5]; int I; /* Compteur */ for (I=0; I<5; I++) printf("%d ", A[I]);
Affectation avec des valeurs provenant de l'extrieur : exemple
int A[5]; int I; /* Compteur */ for (I=0; I<5; I++) scanf("%d", &A[I]);
33
Comme pour les tableaux une dimension, le nom d'un tableau est le reprsentant de l'adresse du premier lment du tableau (c--d l'adresse de la premire ligne du tableau). Les composantes d'un tableau deux dimensions sont stockes ligne par ligne dans la mmoire. Exemple: Mmorisation d'un tableau deux dimensions short A[3][2] = {{1, 2 }, {10, 20 }, {100, 200}}; . 1 2 10 20 100 200 ..
Initialisation et rservation automatique Lors de la dclaration d'un tableau, on peut initialiser les composantes du tableau, en indiquant la liste des valeurs respectives entre accolades. A l'intrieur de la liste, les composantes de chaque ligne du tableau sont encore une fois comprises entre accolades. Pour amliorer la lisibilit des programmes, on peut indiquer les composantes dans plusieurs lignes. Exemples int A[3][10] ={{ 0,10,20,30,40,50,60,70,80,90}, {10,11,12,13,14,15,16,17,18,19}, { 1,12,23,34,45,56,67,78,89,90}}; float B[3][2] = {{-1.05, -1.10 }, {86e-5, 87e-5 }, {-12.5E4, -12.3E4}};
34
Lors de l'initialisation, les valeurs sont affectes ligne par ligne en passant de gauche droite. Nous ne devons pas ncessairement indiquer toutes les valeurs: Les valeurs manquantes seront initialises par zro. Il est cependant dfendu d'indiquer trop de valeurs pour un tableau. Si le nombre de lignes L n'est pas indiqu explicitement lors de l'initialisation, l'ordinateur rserve automatiquement le nombre d'octets ncessaires. int A[][10] = {{ 0,10,20,30,40,50,60,70,80,90}, {10,11,12,13,14,15,16,17,18,19}, { 1,12,23,34,45,56,67,78,89,90}};
2.2. Accs aux composantes Laccs un lment dun tableau deux dimensions se fait selon le schma suivant : NomTableau[Ligne][Colonne] Les lments d'un tableau de dimensions L et C se prsentent de la faon suivante:
/ | A[0][0] | A[1][0] | A[2][0] | . . . | A[L-1][0] \ A[0][1] A[1][1] A[2][1] . . . A[L-1][1] A[0][2] A[1][2] A[2][2] . . . A[L-1][2] . . . . . . . . . . . . . . . \ A[0][C-1] | A[1][C-1] | A[2][C-1] | . . . | A[L-1][C-1] | /
2.3. Affichage et affectation Lors du travail avec les tableaux deux dimensions, nous utiliserons deux indices (p.ex: I et J), et la structure for, souvent imbrique, pour parcourir les lignes et les colonnes des tableaux.
Affichage du contenu d'un tableau deux dimensions
int A[5][10]; int I,J; /* Pour chaque ligne ... */ for (I=0; I<5; I++) { /* ... considrer chaque composante (colonne) */ for (J=0; J<10; J++) printf("%7d", A[I][J]); } Affectation avec des valeurs provenant de l'extrieur int A[5][10]; int I,J; /* Pour chaque ligne ... */ for (I=0; I<5; I++) /* ... considrer chaque composante (colonne) */ for (J=0; J<10; J++) scanf("%d", &A[I][J]);
35
3. Pointeurs et tableaux :
Tout tableau en C est en fait un pointeur constant. Dans la dclaration :
int tab[10] ; int *p; p=tab; /* ou p= &tab[0]; adresse du premier lment */ . ; /* les critures suivantes sont quivalentes : tab[3] ou p[3] ou *(p+3) */
tab est un pointeur constant non modifiable dont la valeur est ladresse du premier lment du tableau. Autrement dit tab a pour valeur &tab[0]. On peut donc utiliser un pointeur initialise tab pour parcourir les lments du tableau. Exemple :
int tab[5] = {2,1,0,8,4} ; int *p ; p= tab ; /* ou p= &tab[0]; adresse du premier lment */ for (int i=0 ; i<5 ; i++) { printf ( %d \n,*p); p++ ; }
4. Tableau de pointeurs :
La dclaration dun tableau de pointeur se fait comme suit : Type * NomTableau [N] Cest la dclaration dun tableau NomTableau de N pointeurs sur des donnes du type Type. Exemple :
char *JOUR[] = {"dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"}; /* affichage des 7 chane de caractres */ for (int I=0; I<7; I++) printf("%s\n", JOUR[I]); /* affichage des premires lettres des jours de la semaine */ for (I=0; I<7; I++) printf("%c\n", *JOUR[I]); /* affichage de la 3 eme lettre de chaque jourde la semaine */ for (I=0; i<7; I++) printf("%c\n",*(JOUR[I]+2));
36
Remarques : Vous ne pouvez pas le droit de : Comparer deux tableaux ; exp : int tab1[3], tab2[3] ; if (tab1>tab2) { } ATTENTION! Affecter un tableau un autre : exp : tab1 = tab2 ; ATTENTION! Dclarer un tableau de taille dynamique comme lexemple suivant : int n = 4 ; char T[n] ;
37
38
Exemple : Fonction permettant d'changer la valeur de 2 variables : Syntaxe qui conduit une erreur :
#include <stdio.h> void PERMUTER (int X,int Y) { int tampon; tampon = X; X = Y; Y = tampon; } void main() { int A = 5 , B = 8; PERMUTER(A,B); printf( A=%d\n , A) ; printf( B=%d\n , B) ; } PASSAGE DES PARAMETRES PAR VALEUR
Syntaxe correcte :
#include <stdio.h> void PERMUTER (int *px,int *py) { int tampon; tampon = *px; *px = *py; *py = tampon; } void main() { int A = 5 , B = 8 ; PERMUTER(&A,&B); printf( A=%d\n , A) ; printf( B=%d\n , B) ; } PASSAGE DES PARAMETRES PAR ADRESSE
39
Explication1: Lors de l'appel, les valeurs de A et B sont copies dans les paramtres X et Y. PERMUTER change bien contenu des variables locales X et Y, mais les valeurs de A et B restent les mmes. Explication2: Lors de l'appel, les adresses de A et B sont copies dans les pointeurs px et py. PERMUTER change ensuite le contenu des adresses indiques par les pointeurs A et B.
Lors de lappel de ces diffrentes fonctions : int tab[5], *p ; LIRE_TAB1 (5, tab) ; LIRE_TAB1 (5,&tab[0]) ; p=tab ; LIRE_TAB1 (5,p) ;
LIRE_TAB2 (5,tab) ; LIRE_TAB3(tab) ;
Remarque : Pour qu'une fonction puisse travailler correctement avec un tableau qui n'est pas du type char, il faut aussi fournir la dimension du tableau ou le nombre d'lments traiter comme paramtre, sinon la fonction risque de sortir du domaine du tableau.
40
#include <stdio.h> main() { /* Prototype de la fonction SOMME */ float SOMME(float *A, int N, int M); /* SOMME(&T[0][0], 3, 4) ); */ /* Dclaration de la matrice */ float T[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9,10,11,12}}; /* Appel de la fonction SOMME */ printf("Somme des lments : %f \n", SOMME((float*)T, 3, 4) ); return 0;
}
Remarque : protection des variables de type tableau lors du passage comme paramtre dans une fonction ; exemple : int lire_tab (const char *t) ;
41
2. Dclaration de structure :
Mthode 1 : dclaration en prcisant un nom pour la structure struct { char nom[20]; char prenom[20]; int n_cin; } personne; Dclare l'identificateur personne comme tant le nom d'un type de structure, compose de trois membres. On peut ensuite utiliser ce type structure pour dclarer des variables, de la manire suivante : struct personne p1,p2; /* qui dclare deux variables de type struct personne de noms p1 et p2 */ Mthode 2 : dclaration en prcisant un nom pour la structure et en dclarant des variables (combiner) struct { char nom[20]; char prenom[20]; int n_cin; } personne p1,p2; Dclare les deux variables p1 et p2 et donne le nom personne la structure. L aussi, on pourra utiliser ultrieurement le nom struct personne pour dclarer d'autres variables : Mthode 4 : dclaration en utilisant typedef typedef struct /* On dfinit un type struct */ { char nom[10]; char prenom[10]; int age; float moyenne; } fiche;
42
fiche f1,f2;
5. Affectation de structures :
On peut affecter une structure une variable structure de mme type. struct personne pr1,pr2; pr1 = pr2 ;
6. Comparaison de structures :
Aucune comparaison n'est possible sur les structures, mme pas les oprateurs == et !=.
43
7. Tableau de structures :
Une dclaration de tableau de structures se fait selon le mme modle que la dclaration d'un tableau dont les lments sont de type simple. Supposons que l'on ait dj dclar la struct personne.
8. Composition de structures :
Une structure permet de dfinir un type. Ce type peut tre utilis dans la dclaration dune autre structure comme type dun de ses champs. Exemple : struct { unsigned int jour; unsigned int mois; unsigned int annee ; } date; struct { char nom[20]; char prenom[20]; struct date d_naissance; } personne;
9. Pointeur et structures :
Supposons que l'on ait dfini la struct personne l'aide de la dclaration :
struct { char nom[20] ; unsigned int age ; } personne;
On dclarera une variable de type pointeur vers une telle structure de la manire suivante :
struct personne *p ;
44
enum jour {LUNDI, MARDI, MERCREDI, JEUDI, VENDREDI, SAMEDI, DIMANCHE}; enum jour j1, j2; j1 = LUNDI; j2 = MARDI; enum jour {LUNDI, MARDI, MERCREDI, JEUDI, VENDREDI, SAMEDI, DIMANCHE} d1, d2; enum {FAUX, VRAI} b1,b2; /* mauvaise programmation */
Si on passe en paramtre une procdure un pointeur vers une struct arith, la procdure testera la valeur du membre typ_val pour savoir si l'union reue possde un entier ou un flottant. Exercice corrig : Crer une structure point{int num;float x;float y;} Saisir 4 points, les ranger dans un tableau puis les afficher. Corrig :
#include <stdio.h> #include <conio.h> typedef struct {int num;float x;float y;} point; void main() { point p[4]; /* tableau de points */ int i; float xx,yy; /* saisie */ printf("SAISIE DES POINTS\n\n"); for(i=0;i<4;i++) { printf("\nRELEVE N %1d\n",i); p[i].num = i; printf("X= ");scanf("%f",&xx); printf("Y= ");scanf("%f",&yy); p[i].x = xx;p[i].y = yy; } /* relecture */ printf("\n\nRELECTURE\n\n"); for(i=0;i<4;i++) { printf("\nRELEVE N%1d",p[i].num); printf("\nX= %f",p[i].x); printf("\nY= %f\n",p[i].y); } printf("\n\nPOUR SORTIR FRAPPER UNE TOUCHE "); getch(); }
46