Les pointeurs

18
Bases de la programmation en C++ 1 Les pointeurs Enormément utilisé en C/C++ ! Pourquoi? A quoi ça sert? Manipuler directement la mémoire de l’ordinateur. Déclarer des tableaux de taille variable. Copier directement des tableaux ou des chaînes de caractères. Utile pour le passage de paramètres.

description

Les pointeurs. Enormément utilisé en C/C++ ! Pourquoi? A quoi ça sert? Manipuler directement la mémoire de l’ordinateur. Déclarer des tableaux de taille variable. Copier directement des tableaux ou des chaînes de caractères. Utile pour le passage de paramètres. …. La notion d’adresse. - PowerPoint PPT Presentation

Transcript of Les pointeurs

Page 1: Les pointeurs

Bases de la programmation en C++ 1

Les pointeurs

Enormément utilisé en C/C++ !

Pourquoi? A quoi ça sert?

Manipuler directement la mémoire de l’ordinateur.

Déclarer des tableaux de taille variable.

Copier directement des tableaux ou des chaînes de caractères.

Utile pour le passage de paramètres.

Page 2: Les pointeurs

Bases de la programmation en C++ 2

La notion d’adresse La mémoire de l’ordinateur peut être vu comme une série de cases.

Ces cases sont repérées par des adresses.

Dans ces cases sont stockées les valeurs des variables (ou des instructions).

Adresses valeurs

65775417 123

65775416 3.2132

65775415 ‘M’

65775414 ‘i’

65775413 ‘a

65775412 ‘m’

Pour accéder à la valeur d’une variable( i.e au contenu de la case mémoire)

Il faut connaître son emplacement(c’est l’adresse de la variable)

Lorsqu’on utilise une variable:

Le compilateur manipule son adressepour y accéder.

Cette adresse est alors inconnue du programmeur

Page 3: Les pointeurs

Bases de la programmation en C++ 3

Qu’est ce qu’un pointeur ?

Un pointeur est une variable qui contient l’adresse d’une variable.

Le stockage en mémoire de la variable (char, int, etc…) est alors sous la responsabilité du programmeur.

On dit que le pointeur pointe sur l’objet pointé.

Le type du pointeur est construit à partir du type de l’objet pointé.

Exemple

Déclaration d’un pointeur

int * Var ; Nom de la variable

Type de l’objet pointéOn a déclaré une variable de type

« Pointeur sur entier »

Cette variable contient l’adresse d’une case mémoire contenant un entier

Page 4: Les pointeurs

Bases de la programmation en C++ 4

Opérateur concernant les pointeurs

& Opérateur d’adresse

* Opérateur d’indirection

-> Membre d’une structure pointée

Soit a une variable et p un pointeur:

&a désigne l’adresse de la variable a

*p désigne la variable pointée par p

Comment accéder à la variable contenue dans un pointeur ?Comment récupérer l’adresse d’une variable ?

Page 5: Les pointeurs

Bases de la programmation en C++ 5

Exemple de déclaration et d’utilisationint i=0; /* Déclare une variable entière. */int *pi; /* Déclare un pointeur sur un entier. */pi=&i; /* Initialise le pointeur avec l’adresse de cette variable. */*pi = *pi+1; /* Effectue un calcul sur la variable pointée par pi,

c’est-à-dire sur i lui-même, puisque pi contientl’adresse de i. */

/* À ce stade, i ne vaut plus 0, mais 1. */

int *px, y, z; // px est un pointeur sur entier // y et z sont des entiers

struct Client{ int Age;};Client Paul;Client *PJean = & Paul;PJean ->Age = 35; /* On aurait pu écrire (* PJean ).Age=35; */

Page 6: Les pointeurs

Bases de la programmation en C++ 6

Attention !

Il faut s’assurer que les pointeur que l’on manipule sont bien initialisé!

Il doivent contenir l’adresse d’une variable valide.

Accéder à la variable d’un pointeur non initialisé revient à:

Ecrire ou lirer, dans la mémoire à un endroit aléatoire.

Plantage à l’exécution du programme.

En général on initialise les pointeurs à la déclaration.

On peut les initialisé comme pointeur NULL.

int * Var; // pour le compilateur Var pointe sur quelque chose (n’importe quoi)

int * Var = NULL; // le compilateur sait que Var ne pointe sur rien

Page 7: Les pointeurs

Bases de la programmation en C++ 7

Comment initialiser un pointeur

Affectation à une variable existante.

int i = 2;

int * P;

P = &i;

65775417

65775416

65775415

65775414

65775413

65775412

i

P

?

2

PXXXXX65775415

= *P

Page 8: Les pointeurs

Bases de la programmation en C++ 8

Comment initialiser un pointeur

Affectation à une variable existante.int i,j; // i, j variables de type intint * pi, *pj; // pi et pj, variables de type « pointeurs vers int »pi=&i; // le pointeur est initialisé à &i, il pointe à l’adresse &i, donc sur i*pi=2; // accès à l’élément pointé, i est mis à 2(*pi)++; // incrémente i qui passe à 3pj=pi; // pj pointe au même endroit que pi (sur i)

int t[10]; // tableau de 10 intpi = &t[2]; // pi pointe sur la case qui contient la valeur T[2]*(pi + 1) = 0; // T[3] est mis à 0 (les éléments d’un tableau se suivent en mémoire)

int i=2, j , k ;int * p1, * p2;p1 = &i; // p1 contient l’adresse de i*p1 = i; // inutile! Car pi=&i donc automatiquement *pi=ip2 = k; // attention l’adresse p2 prend une valeur non défini

//(donc p2 pointe n’importe ou)*p2 = 3; // on écrit quelque chose à un endroit inconnu ! Plantage!« 

Page 9: Les pointeurs

Bases de la programmation en C++ 9

Comment initialiser un pointeur

Allocation dynamique.On réserve la place pour la variable pointée.Syntaxe: Nom_Variable = new type ;

int * P;

P = new int ;

65775417

65775416

65775415

65775414

65775413

65775412

P

?

PXXXXX65775415

*P

Page 10: Les pointeurs

Bases de la programmation en C++ 10

Comment initialiser un pointeur

Allocation dynamiqueIl faut penser à libérer la mémoire après utilisation !Syntaxe: delete Nom_Variable ;Même si on déclare un pointeur dans une fonction (local),

il doit être libéré !

char * C; // C est un pointeur qui pointe sur n’importe quoiC = new char ; // Allocation d’un espace pouvant stocker un caractère

// C pointe sur cet espacedouble * nb ;Nb = new double ; // allocation d’un espace pour stocker un double

double * D;D = new double ;*D = 12.34;delete D ; // libération de l’espace occupé par le double

Page 11: Les pointeurs

Bases de la programmation en C++ 11

Arithmétique des pointeurs

Les opérateur ++, --, +, = ….. Sont définis pour les pointeurs, mais attention, ils s’appliquent aux adresses.

int * P;

…. //allocation

P ++ ;

P = P – 2 ;

int * Q = P + 3;

P

65775417 123

65775416 12

65775415 156

65775414 3

65775413 9

65775412 456

Q

Page 12: Les pointeurs

Bases de la programmation en C++ 12

Pointeur et tableau

Un tableau est en fait un pointeur!

int tableau[3];

int * P = tableau ;

Tableau [2] = 5 ;

*(tableau+1) = 4;

P[0]=1;

65775417

65775416

65775415

65775414

65775413

65775412

tableau

P5

4

1

Page 13: Les pointeurs

Bases de la programmation en C++ 13

Autres exemples avec des tableauxInt tab[3];int * Ptab, x; // Ptab pointeur sur un intPtab = & tab [0]; // Ptab pointe sur le début du tableau

// équivalent à Ptab = tabx = *Ptab; // équivalent à x = tab[0]*(Ptab+ i) = 3; // équivalent à tab[i]=3, *(tab + i) = 3 , Ptab[i]=3

Les allocation dynamiquePossibilité de créer un tableau de taille non constante ! Syntaxe: Type * NomTab;

NomTab = new Type [Taille]; // allocation

Delete [ ] NomTab; // destructionint n = 3;int tab[n]; // INTERDITint * Ptab = new int [n]; // OK….delete [ ] Ptab; // désallocation du pointeur

Page 14: Les pointeurs

Bases de la programmation en C++ 14

Différence pointeur / tableau

Un tableau est un pointeur constant !

On peut donc transtyper un pointeur en tableau mais pas l’inverse!

L’affectation est possible entre pointeur.

int tab[3]; // déclaration d’un tableau de 3 élémentsint * Ptab = new int [3]; // déclaration d’un pointeur avec allocation pour 3 élémentsPtab ++; // OKtab++; // ERREUR tab est constantPtab = tab; // ok les deux pointeur Ptab et tab pointe au même endroit (sur tab[0])Tab = Ptab ; // ERREUR tab est constant

int * tab1 = new int [3]; // déclaration d’un pointeur avec allocation pour 3 élémentsint * tab2 = new int [3]; ;Tab2 = tab1 ; //attention Tab2 pointe maintenant au même endroit que Tab1

char * chaine;chaine = "coucou";

Page 15: Les pointeurs

Bases de la programmation en C++ 15

Affectation de pointeur

int * tab1 = new int [3];

int * tab2 = new int [3];

// remplissage

tab2 = tab1;

delete [] tab2;

delete [] tab1;

65775417

65775416

65775415

65775414

65775413

65775412tab1

tab2

tab2 =

12

3

65

789

31

756

Erreur

Page 16: Les pointeurs

Bases de la programmation en C++ 16

Pointeur et fonction

Un nouveau type de passage de paramètresLe passage de paramètre par pointeur (ou par variable).

// passage par valeurvoid Fonction1(int a) { a = 2; return;}

// passage par référencevoid Fonction2(int & a) { a = 2; return;}

// passage par pointeurvoid Fonction3(int * a) { *a = 2; return;}

int x=0; int y=0; int z=0;Fonction1(x); // la valeur de x ne change pas (passage par valeur)Fonction2(y); // la valeur de y passe à 1 (passage par référence)Fonction3(&z); // la valeur de z passe à 1 (passage par pointeur)// on passe l’adresse de z à la, fonction 3 qui réclame un pointeur en paramètre

Page 17: Les pointeurs

Bases de la programmation en C++ 17

Exempleint LongueurChaine1( char ch[ ] ){ int i = 0; while ( ch[i] != ‘\0’)

i++; return i;}

int LongueurChaine2( char *ch ){ int i = 0; while ( ch[i] != ‘\0’)

i++; return i;}

char tab[3];char * tabP=new char[3];LongueurChaine1(tab);LongueurChaine2(tab);LongueurChaine1(tabP);LongueurChaine2(tabP);

int LongueurChaine3( char *ch ){ int i = 0; while ( *ch != ‘\0’) {

ch++;i++;

} return i;}

Ou encore

Page 18: Les pointeurs

Bases de la programmation en C++ 18

Pointeur et fonction

Mettre un tableau en valeur de retour n’avait pas de sens car l’affectation n’était pas possible ensuite.

Mettre un pointeur en retour de fonction est possible.

char * CreateChaine (const int Size){ char * Chaine = new char [Size];

for (int i=0;i<Size-1;i++) Chaine [i] = 'A';

Chaine [Size-1] = '\0'; return Chaine;

}

int main(){ char * tabP; tabP = CreateChaine(10); // OK // il faudra désallouer tabP //a la fin du programme char tab[10]; tab = CreateChaine(10); /// ERREUR

}