270 likes | 430 Views
Les adresses des fonctions. Pointeur sur une fonction. Pour d éclarer une variable du type pointeur sur une fonction:. tab est l’adresse du premier octet du tableau. int tab [10]; void fon (int i,int j) { . . . }. fon est l’adresse du premier octet implantant la fonction.
E N D
Pointeur sur une fonction • Pour déclarer une variable du type pointeur sur une fonction: tab est l’adresse du premier octet du tableau int tab[10]; void fon(int i,int j) { . . . } fon est l’adresse du premier octet implantant la fonction void (*fon)(int ,int ); • A la déclaration il faut définir: • Le types des paramètres • Le type de retour
Pointeur sur une fonction • Exemple #include <stdio.h> int add(int i,int j); int main() { int (*f)(int,int); int i=1,j=2,k; f=add; k=f(i,j); printf("%d\n",k); k=(*f)(i,j); printf("%d\n",k); k=add(i,j); printf("%d\n",k); k=(*add)(i,j); printf("%d\n",k); printf("%p\n",add); printf("%p\n",f); return 0; } int add(int i,int j) { return i+j; } déclaration d’un pointeur sur la fonction 3 3 3 3 244F:00BA 244F:00BA
Déclarateurs complexes • Formes simplifiées des déclarations – pour les objets simples (tableaux, fonctions, adresses d’objets simples). • Formes des déclarations complexes: tableaux des pointeures, tableaux d'adresses de fonctions , des fonctions rendant des adresses de tableaux , etc. Tableau (de dimension indéterminée) de pointeurs d'entiers int *tabPtr[ ]; int (*ptrTab)[ ]; double (*adrFon)(double); Un pointeur sur un tableau d'entiers Variable de type adresse d’une fonction
Les fonctions et leurs adresses • C permet de manipuler le type fonction rendant un objet de type T (T représente un autre type). • adresse d'un [objet de type] T • tableau de [objets de type] T • En C on aura le droit de travailler avec des variables qui représentent des fonctions, des tableaux de fonctions, des fonctions renvoyant comme résultat d'autres fonctions. • Le concept le plus simpleest celui de variable dont la valeur est une fonction. • Mais toute définition de variable doit entraîner la réservation d'un espace mémoire pour en contenir la valeur.
Les fonctions et leurs adresses • Les fonctions et les données - différences: • Une fois compilée, une fonction est une suite d'octets qui occupe une portion de mémoire comme un tableau de nombres. • La principale différence est dans la possibilité ou l'impossibilité de prédire le nombre d'octets occupés. • Pour un tableau le nombre d'octets occupés est lié avec la déclaration. • Pour une fonction il ne dépend pas de la déclaration (qui ne précise que le type du résultat et le nombre et les types des arguments) mais du nombre d'instructions qui composent la fonction.
Les fonctions et leurs adresses • Le concept plus complexe est celui de variable dont la valeur est l'adresse d'une fonction. • Il n'y a plus de problème de taille (la taille d'une adresse ou pointeur est constante), et la syntaxe pour déclarer une telle variable est: • uneFonction est déclarée comme une variable (un pointeur) destinée à contenir des adresses de fonctions ayant deux arguments, un int et un double, et rendant une valeur double. double (*uneFonction)(int n, double x);
Les fonctions et leurs adresses • L'expression suivante est correcte et représente un appel de la fonction(en supposant k de type int et u et v de type double) : • Comment le programmeur obtient-il des adresses de fonctions ? • De la même manière que le nom d'un tableau représente son adresse de base, le nom d'une fonction représente l'adresse de celle-ci. u = (*uneFonction)(k, v);
Les fonctions et leurs adresses • Ainsi, si on a la définition de fonction: • L'expression maFonction : • possède le type adresse d'une fonction ayant pour arguments un int et un double et rendant un double ; • a pour valeur l'adresse òu commence la fonction maFonction ; • n'est pas une lvalue. double maFonction(int nbr, double val) { . . . }
Les fonctions et leurs adresses • L'affectation suivante est légitime : • A partir de cette affectation (et tant qu'on aura pas changé la valeur de uneFonction) les appels de (*uneFonction) seront en fait des appels de maFonction. uneFonction = maFonction;
Les fonctions et leurs adresses • Le nom d’une fonction – c’est un pointeur constante, qui pointe sur le début de la fonction. • C’est possible de définir les variables – pointeurs vers la fonction. • Après leur initialisation, on peut les utilisées d’appeler les fonctions. type_fon(*nom_fon_point)(liste des arguments); Définition de variable – pointeur vers une fonction
a b h angle x Les fonctions et leurs adresses • Exemple • Faire un programme menu de calculer la surface ou le périmètre d’un trapèze isocèle en utilisant une variable – pointeur sur une fonction (trois paramètres de type double). • Exemple • Faire un programme menu de calculer la surface ou le périmètre d’un trapèze isocèle en utilisant une variable – pointeur sur une fonction (trois paramètres de type double). • Exemple • Faire un programme menu de calculer la surface ou le périmètre d’un trapèze isocèle en utilisant une variable – pointeur sur une fonction (trois paramètres de type double). • Exemple • Faire un programme menu de calculer la surface ou le périmètre d’un trapèze isocèle en utilisant une variable – pointeur sur une fonction (trois paramètres de type double). Le périmètre P=2*a+2*b+2*x S=a*h+x*h La surface
Les fonctions et leurs adresses #include <stdio.h> 1/3 #include <math.h> #include <conio.h> void surf(double,double,double); void perim(double,double,double); void main() { double a,b,x,h,angle; char ch; void (*fonc)(double,double,double); clrscr(); do { printf("\nEntrer angle (gr):"); scanf("%lf",&angle); }while(angle==0 || angle>90); printf("Entrer a="); scanf("%lf",&a); printf("Entrer b="); scanf("%lf",&b); variale pointeur fonc
Les fonctions et leurs adresses angle=angle*2*3.14/360; 2/3 x=b*cos(angle); h=b*sin(angle); do { printf("\n'1' perimetre"); printf("\n'2' surface"); printf("\n'3' fin"); printf("\nEntrer Votre choix:"); ch=getche(); switch(ch) { case '1':fonc=perim; fonc(a,b,x); break; case '2':fonc=surf; fonc(a,x,h); break; case '3':break; default:break; } }while(ch!='3'); } variale pointeur fonc
Les fonctions et leurs adresses void perim(double a,double b,double x) 3/3 { printf("\nPerimetre=%.3lf\n",2*a+2*b+2*x); } void surf(double a,double x,double h) { printf("\nSurface=%.3lf\n",x*h+a*h); } Entrer angle (gr): 45 Entrer a=5 Entrer b=10 '1‘ perimetre '2' surface '3' fin Entrer Votre choix:1 Perimetre=44.148 '1‘ perimetre '2' surface '3' fin Entrer Votre choix:2 Surface=85.341 '1‘ perimetre '2' surface '3' fin Entrer Votre choix:3
Les fonctions et leurs adresses • Fonction rendant un objet - tableau de [objets de type] T • Exemple • Faire une fonction qui rende un pointeur vers une zone de mémoire où sont rangé le racine carré, le carré et le cube d’un nombre entier. #include <stdio.h> 1/2 #include <math.h> #include <stdlib.h> float *fonc(float a) { float *p=(float*)malloc(12); *p=sqrt(a); *(p+1)=a*a; *(p+2)=pow(a,3); return p; }
Les fonctions et leurs adresses • Fonction rendant un objet - tableau de [objets de type] T • Exemple void main() 2/2 { float a, *h; printf("Entrer a="); scanf("%f",&a); h=fonc(a); printf("Le racine carre de %.3f=%.3f\n",a,*h); printf("Le carre de %.3f=%.3f\n",a,*(h+1)); printf("Le cube de %.3f=%.3f\n",a,*(h+2)); } Entrer a=6 Le racine carre de 6.000=2.449 Le carre de 6.000=36.000 Le cube de 6.000=216.000
Les fonctions et leurs adresses • Les rôles respectifs des objets de type fonction et des objets de type adresse d'une fonction sont confus. • La déclaration de fonction sin, extraite du fichier <math.h>, est : • La définition d'une variable de type adresse d'une fonction double à un argument double est : double sin(double); double (*f)(double);
Les fonctions et leurs adresses #include <stdio.h> #include <math.h> void main() { double x,y,z,u,v; double (*f)(double); printf("x="); scanf("%lf",&x); f = sin; y = (*f)(x); z = sin(x); u = f(x); v = (*sin)(x); printf("f=%lf\n",f); printf("y=%lf\n",y); printf("z=%lf\n",z); printf("u=%lf\n",u); printf("v=%lf\n",v); } f et sin sont de même type (adresse d'une fonction) Deux appels équivalents de la fonction sin. L'opérateur d'appel de fonction est définit aussi bien pour une expression de type fonction que pour un expression de typeadresse d'une fonction. x=1 f=0.000000 y=0.841471 z=0.841471 u=0.841471 v=0.841471
Fonctions formelles • Le problème des fonctions formelles, c'est-à-dire des fonctions arguments d'autres fonctions, est résolu en C par l'utilisation d'arguments de type pointeur vers une fonction. • Exemple • Si f est une fonction continue, définie sur un intervalle [a…b ] telle que f(a) et f(b) ne sont pas de même signe, la fonction dicho recherche xε Є [ a…b ] telle qu'il existe x0Є [ a…b ] vérifiant | xε -x0 |<= εet f(x0) = 0. • La fonction dicho détermine xε, qui est une solution de l'équation f(x) = 0 si on tolère une erreur d'au plus ε. • Les arguments de la fonction dicho sont : les bornes aet bde l'intervalle de recherche, la précision εvoulue et la fonction fdont on cherche un zéro.
Fonctions formelles #include <stdio.h> 1/2 #include <math.h> double f(double x){ return x*x*x-2; } double dicho(double a, double b, double eps, double (*f)(double)) { double x; /* hypothèse : f(a) * f(b) <= 0 */ if ((*f)(a) > 0) { x = a; a = b; b = x; } while (fabs(b - a) > eps) { x = (a + b) / 2; if ((*f)(x) < 0) a = x; else b = x; } return x; } L'argument f est déclaré comme un pointeur vers une fonction. - *f est une fonction. - (*f)(x) un appel de cette fonction.
Fonctions formelles void main() 2/2 { double a,b,eps; printf("a="); scanf("%lf",&a); printf("b="); scanf("%lf",&b); printf("eps="); scanf("%lf",&eps); printf("Le racine=%lf\n",dicho(a,b,eps,f)); } a=0.0 b=1.0 eps=1E-8 Le racine=1.000000
Tableau de fonctions • L'utilisation d'un tableau d'adresses de fonctions • Chaque élément du tableau table est formé de deux champs : • le nom d'une fonction standard, sous forme de chaîne de caractères ; • l'adresse de la fonction correspondante. • Le programme: • lit des lignes constituées d'un nom de fonction, suivi d'un ou plusieurs blancs, suivis d'un nombre réel; • évalue et affiche la valeur de la fonction mentionné et appliquée au nombre donné. • La frappe d'une ligne fin arrête le programme.
Tableau de fonctions Les déclarations des fonctions sont écrites dans <math.h> #include <stdio.h> 1/2 #include <string.h> #include <math.h> typedef struct { char *nom; double (*fon)(double); }tab_fon; main() { tab_fon table[] = { "sin", sin, "cos", cos, "exp", exp, "log", log }; char nom[80]; double x; int i; int nbr= sizeof table / sizeof table[0]; Des fonctions sont référencées mais elles ne sont pas en même temps appelées
Tableau de fonctions for(;;) 2/2 { printf("Entrer le nom d'une fonction:"); scanf("%s", nom); if (strcmp(nom, "fin") == 0) break; printf("Entrer la valeur:"); scanf("%lf", &x); for(i = 0; i < nbr && strcmp(table[i].nom, nom) != 0; i++); if (i < nbr) printf("%f\n", (*table[i].fon)(x)); else printf("%s ???\n", nom); } } On cherche àtrouver une fonction dans le tableau avec le nom donné L’appel des fonctions
Tableau de fonctions Entrer le nom d'une fonction: sin Entrer la valeur: 1 0.841471 Entrer le nom d'une fonction: cos Entrer la valeur: 1 0.540302 Entrer le nom d'une fonction: atn Entrer la valeur: 1 atn ??? Entrer le nom d'une fonction: fin