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