Format PDF, 4/page
Transcription
Format PDF, 4/page
1/19 Objectif de ce cours 2/19 Objectifs de ce cours Introduction au langage C - Cours 7 Quelques compléments sur les variables et les procédures Girardot/Roelens I adresse mémoire d’une variable I passage de paramètres de type adresse Un exemple I Septembre 2013 la procédure scanf Introduction au langage C - Cours 7 - Septembre 2013 Introduction au langage C - Cours 7 - Septembre 2013 Girardot/Roelens - Ecole des Mines de Saint-Etienne, 158 cours Fauriel, 42023 Saint-Etienne, France Girardot/Roelens - Ecole des Mines de Saint-Etienne, 158 cours Fauriel, 42023 Saint-Etienne, France Procédures et adresses Un besoin 3/19 Problème Un besoin Utilisation On souhaiterait parfois qu’une procédure puisse modifier des variables de la procédure appelante : I Procédures et adresses procédure d’échange de 2 variables (utilisée dans le programme PGCD) de façon à ce que la valeur de la première soit toujours plus grande que la valeur de la seconde La première idée void echangevars(int X,int Y) {int Z; if (X < Y) { Z=X; X=Y; Y=Z;} } void affichevars(int X,int Y) { printf("X=%d, Y=%d\n",X,Y); } int main(int argc, char *argv[]) {int X=4,Y=6; affichevars(X,Y);echangevars(X,Y); affichevars(X,Y);return 0; } Exécution $ ./echvars X=4, Y=6 X=4, Y=6 Introduction au langage C - Cours 7 - Septembre 2013 Introduction au langage C - Cours 7 - Septembre 2013 Girardot/Roelens - Ecole des Mines de Saint-Etienne, 158 cours Fauriel, 42023 Saint-Etienne, France Girardot/Roelens - Ecole des Mines de Saint-Etienne, 158 cours Fauriel, 42023 Saint-Etienne, France 4/19 Procédures et adresses Un besoin 5/19 Procédures et adresses Débogage Adresses mémoire Adresses mémoire Rappel : machine de Von Neuman Modification de echangevars void echangevars(int X,int Y) {int Z; if (X < Y) { Z=X; X=Y; Y=Z;affichevars(X,Y);} } Exécution $ ./echvars X=4, Y=6 X=6, Y=4 X=4, Y=6 Explication I les variables X et Y de la procédure echangevars sont des copies des variables X et Y de la procédure main I les variables originales ne sont pas modifiées ! Comment s’en sortir ? I utiliser les adresses mémoire ! I la mémoire est constituée de « cases » numérotées I on appelle adresse le numéro de la case mémoire Le langage C permet de manipuler les adresses mémoires I opérateur & : permet d’obtenir l’adresse mémoire d’une variable I opérateur * : permet, à partir d’une adresse mémoire, d’obtenir la valeur que cette adresse contient on peut déclarer des variables de type adresse I I I int *i_addr; double *x_addr; I il existe un type « adresse générique » (adresse de n’importe quoi) : void *addr: I on appelle aussi pointeur une adresse mémoire Introduction au langage C - Cours 7 - Septembre 2013 Introduction au langage C - Cours 7 - Septembre 2013 Girardot/Roelens - Ecole des Mines de Saint-Etienne, 158 cours Fauriel, 42023 Saint-Etienne, France Girardot/Roelens - Ecole des Mines de Saint-Etienne, 158 cours Fauriel, 42023 Saint-Etienne, France Procédures et adresses 6/19 Adresses mémoire 7/19 Procédures et adresses Exemples d’utilisation int i=2,*addr_i; addr_i = &i; printf("*addr_i = %d\n",*addr_i); *addr_i=4; printf("i = %d\n",i); Exécution *addr_i = 2 i=4 Format adresse pour printf printf("addr_i = %p\n",addr_i); printf("addr(addr_i) = %p\n",&addr_i); Exécution addr_i = 7fff2ee0 addr(addr_i) = 7fff2ee4 Paramètres de type adresse Paramètres de type adresse Solution au problème I utiliser des paramètres de la procédure de type adresse I passer à la procédure l’adresse des variables à modifier I la procédure utilise une copie de l’adresse mais modifie la donnée initiale Procédure d’échange de variables (nouvelle version) void echangevars (int *X,int *Y) {int Z; if (*X < *Y) { Z=*X; *X=*Y; *Y=Z; affichevars(*X,*Y); } } Introduction au langage C - Cours 7 - Septembre 2013 Introduction au langage C - Cours 7 - Septembre 2013 Girardot/Roelens - Ecole des Mines de Saint-Etienne, 158 cours Fauriel, 42023 Saint-Etienne, France Girardot/Roelens - Ecole des Mines de Saint-Etienne, 158 cours Fauriel, 42023 Saint-Etienne, France 8/19 Procédures et adresses Paramètres de type adresse 9/19 Procédures et adresses Paramètres de type adresse (2) Un exemple : scanf 10/19 La procédure scanf Procédure de saisie formatée I Procédure principale (nouvelle version) int main(int argc, char *argv[]) {int X=4,Y=6; affichevars(X,Y);echangevars(&X,&Y); affichevars(X,Y);return 0; } Exécution X=4, Y=6 X=6, Y=4 X=6, Y=4 On obtient le résultat attendu ! I I I procédure « réciproque » de printf permet de saisir des données (tapées au clavier) en nombre quelconque (pas forcément une seule !) en respectant un format (vérification) Paramètres I I le premier paramètre de la procédure est le format les paramètres suivants sont les adresses mémoire où doivent être stockées les données saisies Résultat I I le résultat de la procédure est le nombre de données correctement lues (en respectant le format) permet de contrôler si la lecture s’est effectuée correctement ! Introduction au langage C - Cours 7 - Septembre 2013 Introduction au langage C - Cours 7 - Septembre 2013 Girardot/Roelens - Ecole des Mines de Saint-Etienne, 158 cours Fauriel, 42023 Saint-Etienne, France Girardot/Roelens - Ecole des Mines de Saint-Etienne, 158 cours Fauriel, 42023 Saint-Etienne, France Procédures et adresses Un exemple : scanf 11/19 Procédures et adresses Un exemple : scanf Exemples de lectures Exemples de lecture (2) Lecture d’un entier décimal int N; printf("Entrer la valeur de N : "); scanf("%d",&N); printf("La valeur de N lue est %d\n",N); Lecture d’un nombre flottant (float) float x; printf("Entrer la valeur de x : "); scanf("%f",&x); printf("La valeur de x lue est %f\n",x); Lecture d’un nombre flottant (double) double x; printf("Entrer la valeur de x : "); scanf("%lf",&x); printf("La valeur de x lue est %f\n",x); I noter la dissymétrie ! Lectures multiples int N;double x; printf("Entrer les valeurs de N et x : "); scanf("%d%lf",&N,&x); I 12/19 les deux valeurs doivent être séparées par des « blancs » (espaces, tabulations, retours à la ligne) Utilisation d’un format int N;double x; printf("Entrer les valeurs de N et x : "); scanf("(%d,%lf)",&N,&x); I les deux valeurs doivent être saisies entre parenthèses, séparées par une virgule Introduction au langage C - Cours 7 - Septembre 2013 Introduction au langage C - Cours 7 - Septembre 2013 Girardot/Roelens - Ecole des Mines de Saint-Etienne, 158 cours Fauriel, 42023 Saint-Etienne, France Girardot/Roelens - Ecole des Mines de Saint-Etienne, 158 cours Fauriel, 42023 Saint-Etienne, France Procédures et adresses Un exemple : scanf 13/19 Procédures et adresses Exemples de lecture (3) Exécution Entrer les valeurs de N et x : 4 toto Entrer les valeurs de N et x : Entrer les valeurs de N et x : ... ... Problème ! I il reste des caractères tapés au clavier qui n’ont pas été lus (toto), et la procédure scanf échoue indéfiniment ! Solution boucle de saisie tant que les paramètres entrés ne sont pas corrects I procédure __fpurge (non standard !) Introduction au langage C - Cours 7 - Septembre 2013 Introduction au langage C - Cours 7 - Septembre 2013 Girardot/Roelens - Ecole des Mines de Saint-Etienne, 158 cours Fauriel, 42023 Saint-Etienne, France Girardot/Roelens - Ecole des Mines de Saint-Etienne, 158 cours Fauriel, 42023 Saint-Etienne, France Procédures et adresses Un exemple : scanf 15/19 Procédures et adresses Exemples de lecture (4) Nouvelle version int N,resu;double x; for (;;) { printf("Entrer les valeurs de N et x : "); __fpurge(stdin); resu=scanf("%d%lf",&N,&x); if (resu==2) { printf("N=%d, x=%f\n",N,x); break; } } Exécution Entrer les valeurs de N et x : 4 toto Entrer les valeurs de N et x : 4 1.3 N=4, x=1.3 ... 14/19 Exemples de lecture (3) Utilisation du résultat de la procédure int N,resu;double x; for (;;) { printf("Entrer les valeurs de N et x : "); resu=scanf("%d%lf",&N,&x); if (resu==2) { printf("N=%d, x=%f\n",N,x); break; } } I Un exemple : scanf Procédures à résultats multiples Procédures à résultats multiples Problème I on aimerait parfois qu’une procédure puisse rendre plusieurs résultats I I exemple : procédure qui calcule le minimum et le maximum de deux valeurs problème : une procédure ne peut rendre qu’un seul résultat ! Solution I utiliser un passage par adresse ! I la procédure peut rendre un des résultats I pour les autres résultats, on utilise des paramètres de type adresse fournis par la procédure appelante, et « remplis » par la procédure appelée Introduction au langage C - Cours 7 - Septembre 2013 Introduction au langage C - Cours 7 - Septembre 2013 Girardot/Roelens - Ecole des Mines de Saint-Etienne, 158 cours Fauriel, 42023 Saint-Etienne, France Girardot/Roelens - Ecole des Mines de Saint-Etienne, 158 cours Fauriel, 42023 Saint-Etienne, France 16/19 Procédures et adresses Procédures à résultats multiples 17/19 Exemple Procédures et adresses Procédures à résultats multiples Exemple (2) Un autre codage possible void minmax (int X,int Y,int *min,int *max) { if (X < Y) { *min=X; *max=Y; } else { *min=Y; *max=X; } } ... int A,B,m,M; minmax(A,B,&m,&M); Un codage possible (procédure minmax) int minmax (int X,int Y,int *min) { if (X < Y) { *min=X; return Y; } *min=Y; return X; } ... int A,B,m,M; M=minmax(A,B,&m); Introduction au langage C - Cours 7 - Septembre 2013 Introduction au langage C - Cours 7 - Septembre 2013 Girardot/Roelens - Ecole des Mines de Saint-Etienne, 158 cours Fauriel, 42023 Saint-Etienne, France Girardot/Roelens - Ecole des Mines de Saint-Etienne, 158 cours Fauriel, 42023 Saint-Etienne, France Procédures et adresses Autres utilisations du passage par adresse 19/19 Autres utilisations Le mécanisme de copie des paramètres peut être coûteux (en temps et en mémoire) I I on utilise parfois un passage par adresse pour éviter cette recopie même si la procédure appelée ne doit pas modifier les données Certaines procédures fournies avec le système utilise un passage par adresse I I I la procédure time() (permet de récupérer la date courante) son prototype est time_t time (time_t *addr) on l’utilise sous la forme time_t t0; /* premiere ecriture */ (void) time(&t); /* ecriture equivalente */ t=time(0); Introduction au langage C - Cours 7 - Septembre 2013 Girardot/Roelens - Ecole des Mines de Saint-Etienne, 158 cours Fauriel, 42023 Saint-Etienne, France 18/19