You are on page 1of 11

Chapitre 8 : Pointeurs & Allocation mmoire

81

Chapitre 8

Pointeurs & Allocation mmoire

Mohamed N. Lokbani

v1.01

POO avec C++

Chapitre 8 : Pointeurs & Allocation mmoire

82

1. Dfinitions
- La notion de pointeur est spcifique aux langages C et C++.
- Une adresse est un emplacement donn en mmoire.
- Un pointeur est une variable qui contient ladresse dune autre variable de nimporte quel type.
- La syntaxe (dclaration ou dfinition) est comme suit :
Type *identificateur ;
Ou bien
Type* identificateur ;
int *ptr ;

- Le pointeur ptr contient ladresse mmoire dune zone mmoire capable de contenir une variable de
type int
- La dfinition dun pointeur nalloue en mmoire que la place mmoire ncessaire pour stocker ce
pointeur et non pas ce quil pointe !
- Il est prfrable dinitialiser le pointeur avant de lutiliser sinon bonjour les dgts !
- Un pointeur sur un type void pointe une zone sans type.
void *ptr ;

Mohamed N. Lokbani

v1.01

POO avec C++

Chapitre 8 : Pointeurs & Allocation mmoire

83

int main() {
int i = 99;
int *ptr; // dclaration
ptr = &i; // initialisation
return 0;
}

Adresse
mmoire

Contenu
mmoire

Variables

15478

13256

ptr

13256

99

- Loprateur unaire & fournit ladresse en mmoire dune variable donne.


- Il permet donc dinitialiser la valeur dun pointeur.
int i=99 ; Une zone mmoire sera rserve pour contenir la
variable i . Cette zone mmoire va avoir un emplacement, par
exemple 13256 . La variable i contient une valeur 99 .
Cette valeur est stocke dans cet emplacement mmoire.
int *ptr ; Une zone mmoire sera rserve pour contenir la
variable ptr qui est un pointeur sur un int . Cette zone
mmoire va avoir un emplacement, par exemple 15478 . La
variable ptr va contenir ladresse dun lment du type
int .
&i correspond lemplacement mmoire de i = 13256
ptr = &i = 13256

Mohamed N. Lokbani

v1.01

Chapitre 8 : Pointeurs & Allocation mmoire

POO avec C++

84

- Loprateur unaire dindirection * permet dobtenir la valeur dun lment ( drfrencer ) dont
ladresse est contenue dans le pointeur.
int i=99 ;
int *ptr ;
ptr = &i ;
*ptr = *ptr + 1; ( i=i+1) On incrmente le contenu de ptr de 1.
(*ptr)++; ( i++)

- Attention : ne pas confondre entre dclaration et drfrencement. Pour drfrencer un pointeur, il


faudrait quil en existe dj. Si un pointeur existe, penser linitialiser sinon catastrophes en vue !
- La constante NULL dfinit la valeur dun pointeur ne pointant sur rien.
- Sa valeur est lentier 0 .
- Elle est utilise pour des raisons de lisibilit et de scurit.

int *ptr=NULL ;
if(ptr == NULL)
cout << "Attention, pointeur NUL \n" ;

Mohamed N. Lokbani

v1.01

POO avec C++

Chapitre 8 : Pointeurs & Allocation mmoire

85

- On peut casser le lien entre pointeur et llment point. Le dbut de la fin ! Catastrophes lhorizon !
- Le pointeur est dtruit mais pas l'lment point. Si rien ne pointe plus sur lui, on peut perdre sa trace
dans la mmoire de l'ordinateur... des fuites de mmoire une sacre passoire !
- L'lment point peut disparatre alors que le pointeur continue de pointer sur lui ! Ae ! Risque important
de plantages alatoires.
- Initialiser systmatiquement les variables de type pointeur.

2. Pointeurs et Tableaux
- Les tableaux sont en ralit des pointeurs.
- Le nom d'un tableau est un pointeur constant sur le premier lment de celui-ci.
- En C++, une chane de caractres est considre comme un tableau de caractres dont le dernier lment
est le caractre \0 .
- Quand on travaille sur un tableau, on a le choix dutiliser un indice ou bien travailler avec un pointeur.

Mohamed N. Lokbani

v1.01

POO avec C++

Chapitre 8 : Pointeurs & Allocation mmoire

86

char *ptab ; // pointeur sur un char


char tab[10]; // tableau de 10 char
ptab = &tab[0];
tab[0] = 'a' ;  *ptab = 'a' ;
tab[3] = 'd' ;  *(ptab+3) = 'd';

ptab contient
ladresse de
llment se
trouvant lindex
0  ptab = tab ;

int tab[3] = {1, 2, 3};


int *ptr = tab;
for (int i = 0; i < 3; ++i){
cout << ptr[i] << endl; // 1 2 3
}

- Attention aux affectations sans aucun sens !


char tab1[10], tab2[10] ;
tab1 = tab2 ; //  cette expression 2 = 3 Incorrecte !

Mohamed N. Lokbani

v1.01

POO avec C++

Chapitre 8 : Pointeurs & Allocation mmoire

87

3. Arithmtique des pointeurs


- Lincrmentation (resp. dcrmentation) exprime le fait quon veuille atteindre llment suivant (resp.
prcdent).
- Le rsultat nest correct que si llment point est situ dans le mme tableau.
int *ptr ;
ptr++;
ptr = ptr+1 ;

- Laddition de deux pointeurs na pas de sens.


- La soustraction de deux pointeurs (ayant le mme type) situs dans le mme tableau retourne le nombre
dlments qui les sparent.
- Un pointeur ne peut tre compar qu un pointeur du mme type ou un pointeur NULL.
- On ne doit affecter un pointeur quune valeur de pointeur ayant le mme type sinon bonjour les dgts.
On ne saura plus qui est quoi et o ? La magie des pointeurs !!!

Mohamed N. Lokbani

v1.01

POO avec C++

Chapitre 8 : Pointeurs & Allocation mmoire

88

4. Les tableaux et les chanes


- Un tableau de chane de caractres peut tre initialis de la manire suivante:
char msg[] = "Bonjour" ;

char msg[] = {'B', 'o', 'n', 'j', 'o', 'u', 'r', '\0'} ;

- La dimension du tableau msg est facultative.


- Elle est calcule par le compilateur.
- Le compilateur place ce genre de tableaux (dont il se charge de calculer leur taille) dans une zone
mmoire statique. Il faut faire donc attention lors de la modification du contenu de ce genre de tableaux.
(Ce cas sera illustr dans une des sances de dmonstration).
- En dehors de la dclaration, il nest pas possible daffecter une chane de caractres un tableau.
- Il faut passer par des fonctions appropries. (Elles seront dailleurs tudies plus tard dans le cours).
char msg[15] ;
msg = "Bonjour" ; // INCORRECT

Mohamed N. Lokbani

v1.01

POO avec C++

Chapitre 8 : Pointeurs & Allocation mmoire

89

4. Tableau deux dimensions


- Les tableaux deux dimensions sont des tableaux de tableaux.
- Les indices de droite sont les plus internes. Le compilateur a besoin de les connatre pour savoir comment
naviguer lintrieur du tableau.
- Les tableaux n dimensions sont des tableaux de tableaux n-1 dimensions.
int tab[2][4] ;
Un tableau de 8 entiers
int a[2][4] = {{1,2,3,4},{5,6,7,8}} ;
ou plus simplement
int a[2][4] = {1,2,3,4,5,6,7,8} ;

Colonnes

0
1

Lignes

0
1
5

1
2
6

2
3
7

3
4
8

Un tableau de 2 lignes et 4 colonnes

- En mmoire les donnes de ce tableau seront organises comme suit :

Mohamed N. Lokbani

v1.01

POO avec C++

Chapitre 8 : Pointeurs & Allocation mmoire

..

90

1ere colonne

..

2e colonne
dtab

- Le tableau est donc stock comme un tableau une seule dimension.


- Laccs un lment donn se fait par le calcul de cette formule :
index = i* nbreColonnes + j
tab[0][2] i.e. i = 0, j = 2  index = 0*4 + 2 = 2  dtab[2]
tab[1][2] i.e. i = 1, j = 2  index = 1*4 + 2 = 6  dtab[6]

Mohamed N. Lokbani

v1.01

POO avec C++

Chapitre 8 : Pointeurs & Allocation mmoire

91

5. Tableau de pointeurs
- Soit la dfinition suivante :
char tab[10][20] ;
un tableau de chane de caractres : 300 caractres

- Si chaque caractre occupe 1 octet en mmoire, cette dfinition rserve 300 octets en mmoire.
- On peut dfinir un tableau de pointeurs sur des chanes de caractres comme suit :
char *tab[10] ;
un tableau de 10 pointeurs sur des chanes de caractres.

- On ne prcise pas la taille des chanes.


- Cette taille peut-tre donc variable.
- Ainsi, cette faon de procder permet de noccuper que lespace mmoire requis.
char *tab[] = {"Cours","IFT1166","C++"} ;
initialisation dun tableau de pointeurs

Mohamed N. Lokbani

v1.01

POO avec C++

Chapitre 8 : Pointeurs & Allocation mmoire

92

C o

\0

tab[0]
I

F T 1

\0

tab[1]
tab[2]

C + + \0

tab  &tab[0] : ladresse du premier lment du tableau


*tab  tab[0] : le premier lment du tableau, ladresse du
premier caractre de la chane "Cours"
tab[1] : ladresse sur le premier caractre de la chane
"IFT1166"
*(tab+1)  tab[1]
*tab[1] : est le caractre point par tab[1] : cest le
caractre 'I' de la chane "IFT1166"
**tab  *tab[0] : le caractre 'C' de la chane "Cours"
**(tab+1)  *tab[1] : cest le caractre 'I' de la chane
"IFT1166"
*(tab[2]+1)  tab[2][1] : cest le premier caractre '+' de
la chane "C++"

Mohamed N. Lokbani

v1.01

POO avec C++

Chapitre 8 : Pointeurs & Allocation mmoire

93

6. Allocation mmoire
- Loprateur new permet une allocation dynamique de lespace mmoire.
- Loprateur delete permet de librer la mmoire alloue.
Langage
C
C++
Java

allouer
malloc
new
new

supprimer
free
delete
--------

- new T retourne un pointeur de type T* non nul;


- delete P libre l'espace mmoire point par P.
Allouer
pour un lment
pour un tableau de taille DIM

new T
new T[DIM]

supprimer
delete P
delete [] P

- new T(valeur) allocation d'un pointeur de type T* non nul et initialisation du pointeur avec valeur
(valable uniquement pour un lment).

Mohamed N. Lokbani

v1.01

POO avec C++

Chapitre 8 : Pointeurs & Allocation mmoire

94

#include <iostream>
int main() {
double* ptr;

Pointeur du type double

ptr = new double;

Allocation de l'espace pour stocker un double

*ptr = 126789.89;

Affectation d'une valeur double

int* tab = new int[20];

Sur une ligne, allocation d'un tableau de 20 int

tab[5] = 78;

Affectation d'une valeur tab[5]

int* autre = new int(250);

Allocation d'un espace mmoire pour stocker un


int et initialisation de cet espace.

delete ptr;
delete autre;
delete [] tab;

Libration de l'espace allou pour ptr


Libration de l'espace allou pour autre
Libration de l'espace allou pour le tableau tab

return 0;
}

Mohamed N. Lokbani

v1.01

POO avec C++

Chapitre 8 : Pointeurs & Allocation mmoire

95

7. Constantes et pointeurs
- La valeur d'une constante ne peut pas tre modifie.
- Ladresse d'une constante ne peut pas tre affecte une variable.
1er cas de figure
const int j=100;
j=50;

Erreur, la variable j est constante, on


ne peut pas modifier sa valeur

int* ptr;
ptr=&j;

Erreur, car on risque de modifier une


variable dclare comme tant
constante

- A vrai dire, le compilateur g++ ne signale qu'un warning!


- Il modifie le type de j de const int vers int uniquement.
- Autant crire les choses proprement:
 soit garder j comme une constante et enlever ptr=&j
 sinon dclarer j comme tant un int et garder ptr=&j.

Mohamed N. Lokbani

v1.01

POO avec C++

Chapitre 8 : Pointeurs & Allocation mmoire

96

2e cas de figure
const int* ptr;

ptr pointe sur une variable constante,


mais ptr n'est pas une constante

ptr = &j;
*ptr=200;

OK
Erreur car on tente de modifier la
valeur pointe par ptr qui est une
constante!

int k=30;
ptr = &k;

OK

3e cas de figure
int a = 10;
int* const ptr = &a;

ptr est une constante mais pas la

variable pointe
int b = 20;

Mohamed N. Lokbani

ptr = &b;

Erreur, l'adresse est constante

*ptr = 400;

OK, et par la mme occasion a=400

v1.01

POO avec C++

Chapitre 8 : Pointeurs & Allocation mmoire

97

4e cas de figure
int i=20;
const int j=10;
const int* const ptr = &j;

ptr est constant et pointe sur une

valeur constante
Erreur, on tente de modifier la valeur
de j qui est constante

*ptr=30;
ptr=&i;

Erreur, on modifie l'adresse pointe par


ptr qui est constante

Mohamed N. Lokbani

v1.01

Chapitre 8 : Pointeurs & Allocation mmoire

POO avec C++

98

8. Conversion de pointeurs
- Type void* dnote un pointeur quelconque.
- Ansi-C permet de convertir implicitement:
type*  void*
et
void*  type*

- En C++,
La conversion void*  type* est INTERDITE.

Mohamed N. Lokbani

v1.01

POO avec C++

Chapitre 8 : Pointeurs & Allocation mmoire

99

int* p;
void* v;
v = p;

OK conversion vers void* acceptable


ERREUR, conversion non autorise en
C++, mais OK en C

p = v;

Le compilateur n'a aucune information pour interprter le contenu de la variable afin de la convertir.
Le compilateur ne connat pas le nombre prcis d'octets auquel le pointeur rfre.
Dans le cas d'un pointeur vers void, il ne peut pas dterminer le nombre d'octets partir du type.
Il est ncessaire de faire un cast explicite, i.e.:

p = (int*) v;

criture la C
(valable en C++)

p = static_cast< int* >(v);

Nouveau style
(non valable en C)

Mohamed N. Lokbani

v1.01

POO avec C++

Chapitre 8 : Pointeurs & Allocation mmoire

100

9. Conversion de type
- Nous avons dj mentionn les 4 nouveaux oprateurs introduits en C++ pour permettre de forcer la
conversion de type.
9.1. static_cast
- En plus des proprits prcdemment mentionnes, il peut effectuer aussi les oprations de conversion
standard de void* vers un int* par exemple.
- Par contre, cet oprateur ne permet le forage de types const vers non const ainsi que le forage de
types sans relation.
const int x = 8;
int *p = static_cast <int *> (&x);

int j =250;
int *p = static_cast <int *> (j);

Mohamed N. Lokbani

v1.01

Erreur : la variable x est


constante, on tente une
conversion constante vers
non constante

Erreur : Le pointeur p est du


type int* et la variable j
est int, il n'y a pas de
relation entre les deux types

POO avec C++

Chapitre 8 : Pointeurs & Allocation mmoire

101

9.2. const_cast
- Cet oprateur permet uniquement la conversion de types const vers non const.
const int x = 8;
int *p = const_cast <int *> (&x);

int y = 8;
int *r = const_cast <int *> (&y);
double yz = 8.7;
int *rr = const_cast <int *> (&yz);

Ok! Conversion const vers


non const

Inutile car y n'est pas const


Erreur+Inutile! Erreur car
conversion de type double
vers int or le rle de
const_cast se limite la
conversion const vers non
const

Mohamed N. Lokbani

v1.01

POO avec C++

Chapitre 8 : Pointeurs & Allocation mmoire

102

9.3. reinterpret_cast
- Cet oprateur est utilis essentiellement pour la conversion de types de relation diffrente (non standard),
int et int*, void* et int etc.
- Il ne permet pas la conversion const vers non const.

int j =250;
int *p = reinterpret_cast <int *> (j);

Ok! Conversion de types:


int vers int* mais

- Faire trs attention lors de l'utilisation de cet oprateur.


int j =250;
int *p = reinterpret_cast <int *> (j);
cout << *p;

Mohamed N. Lokbani

v1.01

Elle peut provoquer un


comportement
bizarre
(parfois mme une erreur
due un accs interdit
une zone mmoire) lors de
l'excution du programme

POO avec C++

You might also like