Introduction générale à la programmation/Pointeurs

Début de la boite de navigation du chapitre
Pointeurs
Icône de la faculté
Chapitre no 7
Leçon : Introduction générale à la programmation
Chap. préc. :Récursivité
fin de la boite de navigation du chapitre
En raison de limitations techniques, la typographie souhaitable du titre, « Introduction générale à la programmation : Pointeurs
Introduction générale à la programmation/Pointeurs
 », n'a pu être restituée correctement ci-dessus.

Les pointeurs

modifier

Les pointeurs sont une notion souvent mal expliqué de la programmation, autant par sa délicatesse d’utilisation ou par le fait que les débutants ont souvent du mal à comprendre à quoi cela peut servir parce que beaucoup d'enseignants l'expliquent en partant de la fin.

Concrètement, chaque langage a sa propre définition de pointeurs, mais en programmation, un pointeur est une variable destinée à contenir une adresse.

(Il est à noter qu'un pointeur peut contenir l'adresse d’un autre pointeur. Cela fait un pointeur de pointeur. Un tel besoin n’est pas extrêmement courant mais peut arriver. En particulier pour les tableaux multidimensionnels. ex: double**** vTableau; vTableau[x][y][z]= new double;)

Début de l'exemple
Fin de l'exemple


Quel est l’intérêt des pointeurs

modifier
  • En langage C, une méthode ne peut retourner au maximum qu'une seule valeur.

L'utilisation de pointeurs en langage c permet aux arguments (valeurs qui entrent dans une méthode) de conserver leurs modifications. Cela veut dire que grâce aux pointeurs une méthode peut retourner autant de valeurs qu'elle a d'arguments.

  • Une méthode fait des copies des arguments passés par valeurs, et travaille avec ces copies. Ceci évite de modifier les valeurs des arguments par inadvertance. Cela signifie aussi que sur des arguments 'gros' (des grands tableaux par exemple), il faut que la méthode ait copié la totalité du tableau avant de travailler dessus.
Début de l'exemple
Fin de l'exemple

Attention, on travaille directement avec les données originales. Il vaudrait donc mieux avoir une copie de ces fichiers avant d'appeler la méthode.

  • En langage C le nom d'une méthode est un pointeur. On peut donc l’utiliser comme argument d'une fonction.

DONC :

  1. Les pointeurs servent à éviter de saturer la pile avec un bloc de données trop important. Il vaut mieux créer un tableau de 10000 chaînes de caractères en tas(gestion par la mémoire virtuelle) que de le créer dans la pile avec tous les problèmes de gestion que cela implique (Surcharge, effondrement de la pile, buffer overflow, réécriture d'adresse de retour, etc ...). De plus avec les pointeurs multiples le contrôle sur les éléments d’un tableau multidimensionnel est beaucoup plus simple et aisé que sur un tableau monolithique en pile.
  2. L'utilisation de pointeurs est recommandé par le "Design Pattern" "FlyWheight" qui permet d'attribuer à un nombre conséquents d'objets un nombre limité de valeurs sans surcharger la mémoire avec toutes les valeurs possibles.
  3. Les pointeurs permettent de s'affranchir de la notion de méthode. (n entrées et une ou zéro sortie)
  4. Avec l’utilisation des pointeurs, on peut avoir n entrées et n+1 sortie (+1 = return)
  5. On préférera utiliser des tableaux, des structures, ou mieux, des objets pour résoudre ce type de problèmes.
  6. En C, les paramètres sont passés par valeur.
  7. Le c fait une copie des arguments de la méthode, et travaille avec cette copie.
  8. Les pointeurs permettent de passer les valeurs par adresses (en copiant la valeur de l'adresse), donc de travailler directement sur les données avec le risque de corrompre les données.
  9. On peut utiliser directement le nom d'une méthode comme argument parce que c’est aussi un pointeur. C’est d'ailleurs ce qui a permis la création du compilateur objet en C++ par Bjarns STROUSTRUP en utilisant une table de virtualisation intégré à une structure et des pointeurs sur méthodes.

Exemple d'algorithme pour l’utilisation de pointeurs de fonctions

modifier
Début de l'exemple
Fin de l'exemple



Début de l'exemple
Fin de l'exemple


Exemple de code pour d’utilisation de pointeurs de fonctions

modifier

Exemple numérique

modifier
  • Testé sous Code Block (Windows,Linux).
  • Passer deux pointeurs de fonctions à une fonction.
  • Ici on passe les deux fonctions f et g à la fonction f1_o_f2().
  • La même fonction peut calculer gof, fog et fof...
  • On peut remarquer que les pointeurs de fonctions ont les mêmes types arguments que les fonctions qu’ils vont recevoir.


/* ------------------------------ */
#include <stdio.h>
#include <math.h>
/* ------------------------------ */


/* ------ Fonction f ------------ */
double f(double x){return( pow(x,2.));}
/* ------------------------------ */
char feq[] = "x**2";
/* ------------------------------ */

/* ------ Fonction g ------------ */
double g(double x){return(2.0*x + 3.0);}
/* ------------------------------ */
char geq[] = "2.0*x + 3.0";
/* ------------------------------ */


/* -Fonction fog (g suivie de f)-*/
double f1_o_f2(
double (*P_f1)(double x),/* Pointeur pour la première fonction */
double (*P_f2)(double x),/* Pointeur pour la deuxième fonction */
double a
)
{
 return((*P_f1)( ((*P_f2)(a))) );
}
/* ------------------------------ */


/* ------------------------------ */
int main(void)
{
double a = 2.0;

 printf(" f : x-> %s\n", feq);
 printf(" g : x-> %s\n", geq);
 printf(" \n\n");


   printf(" f(g(%.0f)) = %6.1f\n", a, f1_o_f2(f,g,a));
   printf(" g(f(%.0f)) = %6.1f\n", a, f1_o_f2(g,f,a));
   printf(" f(f(%.0f)) = %6.1f\n", a, f1_o_f2(f,f,a));


 printf("\n\n Press return to continue.\n");
 getchar();

 return 0;
}


Résultat ;

f : x-> x**2
g : x-> 2.0*x + 3.0

f(g(2)) = 49.0
g(f(2)) = 11.0
f(f(2)) = 16.0


Press return to continue.

Exemple graphique (avec Gnuplot)

modifier
  • Testé sous Code Block (Windows,Linux).
  • Passer un pointeurs de fonctions à une fonction.


  • La fonction Gplt() dessine f(x) et g(x)...
  • On peut remarquer que les pointeurs de fonctions ont les mêmes types arguments que les fonctions qu’ils vont recevoir.
/* ------------------------------ */
#include <stdio.h>
#include <math.h>
/* ------------------------------ */

/* --- Dessinons f et g --------- */
double f(double x){return( pow(x,2.));}
double g(double x){return(2.0*x + 3.0);}
/* ------------------------------ */


/* Le fichier de points: [a,f(a)] */
void Gplt(
double (*P_f)(double x)
)
{
FILE *fp;
double a;

        fp = fopen("data","w");
   for(a = -5.0; a <= 5.0; a += 0.3)
       fprintf(fp," %6.3f   %6.3f\n",
                    a,      ((*P_f)(a)) );
 fclose(fp);
}


/* ------------------------------ */
int main(void)
{

 printf("f) Dans gnuplot -> plot \"data\" ");
    Gplt(f);
 getchar();

 printf("g) Dans gnuplot -> plot \"data\" ");
    Gplt(g);


 printf("\n\n Press return to continue.\n");
 getchar();

 return 0;
}


Pour approfondir ce travail : Mathc Home Edition t01/Gnuplot