1 Pointeurs, références, alias et tableaux 1
1.1 Définitions Un pointeur est une variable contenant l'adresse d'un objet en mémoire. Un pointeur est déni par le couple (type, adresse) de l'objet pointé. déclaration : type *identificateur; exemple : p est un pointeur sur un entier, i.e. p contient l'adresse d'une case mémoire contenant un entier. int *p; Si p est un pointeur sur le type Type alors on accède à la valeur pointée par *p exemple float *p; *p=2.0; si x est une variable de type Type, alors &x est l'adresse de x, c'est donc un pointeur sur Type exemple float x; float *px; px = &x; si x est un float, alors float &xalias = x est une déclaration légale, xalias est un alias de x. exemple float x; float &y = x; // initialisation obligatoire 2
1.2 Pointeurs et tableaux en C++, pointeurs et tableaux sont très liés : int T[5] ; int *p ; Attention, l'indice d'un tableau à n élément varie de 0 à n-1 l'instruction p = T ; est autorisée car T est aussi un pointeur d'entiers ; équivaut à p = &T[0]; p pointe sur le premier élément de T p+i pointe sur le ième élément suivant; *(p+i) est égal à T[i]. Le nom d'un tableau est un pointeur constant sur le premier élément du tableau. Allocation dynamique d'un tableau de n éléments de type Type : Type *a; a = new Type[n]; delete[]a; //allocation memoire //liberation memoire si l'allocation réussit, new retourne un pointeur sur le premier élément de la mémoire allouée, sinon il retourne NULL. Le programmeur qui alloue de la mémoire dynamiquement a en charge la libération de mémoire qui n'est en aucun cas automatique au cours du déroulement du programme. 3
1.3 Chaînes de caractères une chaîne de caractères est un tableau de caractères Certaines fonctions sont disponibles. Ces fonctions sur chaînes de caractères sont déclarées dans <string.h>. Sous UNIX, une aide en ligne est disponible via la commande man string. La n d'une chaîne de caractère est signalée par un caractère NULL (ou '\0'), inséré par le compilateur. on accède aux constantes de type chaîne de caractères au moyen d'un pointeur de type char, pointant sur le premier élément de la chaîne, par exemple char *s; lors de l'instruction char * s=ceci est un message; la chaîne n'est pas recopiée dans s mais s contient l'adresse du premier élément de cette chaîne. Les fonctions les plus utiles : char *strcpy(char *dest, const char *src); recopie src dans dest (la place mémoire de dest doit avoir été réservée) char *strcat(char *dest, const char *src); recopie src à la n de dest (la place mémoire de dest doit avoir été réservée) size_t strlen(const char *s); retourne la taille de la chaîne s La classe string permet une manipulation plus intuitive et ecace des chaines de caractères. Par exemple : # include <iostream> # include <string> using namespace std; int main(void) { string S("Puiseux"); cout << endl << S +" Pierre"<< flush; return 0; } 4
1.4 Tableaux multidimensionels, matrices déclaration : type identificateur [dim1][dim2]; exemple : const int MAXDIM=100 ; long double a[maxdim][maxdim] ; les éléments sont rangés par lignes : a[i] est (l'adresse du premier élément de) la ligne numéro i *a[i] est le premier élément de la ligne numéro i. a[i]+j est l'adresse du jème élément de la ligne i a[i][j] est l'élément ième ligne, jème colonne *a[i]+j est l'élément ième ligne, jème colonne aussi Allocation dynamique d'une matrice de taille n*n : double **a; //allocation a = new (double *)[n]; for (i=0;i<n;i++) a[i] = new double[n]; //liberation for (i=0;i<n;i++) delete []a[i]; delete[]a; si l'allocation réussit, new retourne un pointeur sur le premier élément de la mémoire allouée, sinon il retourne NULL 5
T[i] T[i][j] 1.5 Remarques sur les pointeurs le C++ n'eectue pas de vérication sur les indices de tableau. C'est au programmeur de prendre ses précautions. a[i] est évalué par le C++ comme *(a+i) dans le cas de transmission de tableau en paramètre d'une fonction, seule l'adresse du premier élément est transmise. La valeur NULL (en fait 0) pour un pointeur est caractéristique d'un pointeur mal initialisé ou mal déclaré. L'incrémentation d'un pointeur p++ (ou p--) a pour eet d'incrémenter p de sizeof(p) octets. Int T[10][5][2]; est un tableau à 10 éléments, chaque élément étant une matrice à 5 lignes, 2 colonnes. désigne donc une matrice (deux dimensions) ; désigne un tableau à une dimension (ou vecteur) d'entiers ; T[i][j][k] désigne un entier. 6
1.6 Pointeurs de fonctions une fonction n'est pas une variable. Néanmoins, elle a une adresse en mémoire. On peut donc dénir une variable qui pointe sur une fonction. Déclaration : double (*f) (int,float); int (*g) (); f est un pointeur sur une fonction prenant un int et un float en arguments et dont le résultat est de type double. g est un pointeur sur une fonction sans arguments dont le résultat est de type int. A distinguer de double *f(); qui désigne une fonction renvoyant un pointeur sur double. Peut s'utiliser lorsque la fonction à utiliser peut varier, par exemple pour une méthode de Newton générique (1d), on dénira par exemple : double Newton(double(*f)(double);int itmax); { /*ici, on peut utiliser la fonction f comme on le désire*/ }; //appel : double solution ; double f(double x) ; solution = Newton(f,ITMAX); 7
1.7 Allocation dynamique de mémoire Opérateurs new et delete exemple : voir ([1.2] et [1.4]). A privilégier par rapport à la solution suivante (malloc). On peut trouver aussi des fonctions de la famille malloc (langage C): void *malloc(size_t size) ; aloue un bloc de mémoire de size octets dans la zone de mémoire appelée tas (heap). NB : l'instruction calloc(n,s) est équivalente à malloc(n*s). Si l'allocation réussit, malloc renvoie un pointeur sur le bloc nouvellement alloué. Si la place disponible est insusante ou si size vaut 0, malloc renvoie NULL. Le contenu du bloc n'est pas modié. Si l'argument size vaut 0, alors malloc renvoie NULL. exemple : allocation mémoire pour une matrice n*n (produit un résultat analogue à [1.2] et [1.4]): /*tableau de n pointeurs 0-->n-1 */ if ((a = (double * *) malloc (n*sizeof(double *))) == NULL) FatalWarning ("Memoire insuffisante \n"); for (i=0; i<n; i++) if ( (a[i] = (double *) malloc(n*sizeof(double)))== NULL) FatalWarning ("Memoire insuffisante \n"); /* Après utilisation, libérer la mémoire par free */ for (i=0; i<n; i++) free(a[i]); free(a); 8