Professional Documents
Culture Documents
Mmoire
La mmoire d'un ordinateur est compose d'un grand nombre d'octets (une valeur
entre 0 et 255) :
adresse
octet
0
1
2
3
Chaque octet est repr par une adresse, qui est un nombre entier.
contenu
24996
25000
25004
25008
25012
25016
25020
L'oprateur &
On peut obtenir l'adresse d'une variable grce l'oprateur &:
Par exemple:
int a(3);
cout << a << endl;
cout << (unsigned int)(&a) << endl;
va afficher pour cet exemple:
3
25004
adresse
contenu
24996
25000
25004
25008
25012
25016
25020
adresse
contenu
24996
int * p;
p = &a;
25000
25004
25008
p contient l'adresse de a.
25012
25016
25108
3
?
25004
?
p
adresse
contenu
24996
25000
25004
3
?
25008
25012
25016
25108
3
a
p
L'oprateur *
L'oprateur * permet d'accder la valeur stocke une adresse:
cout << *p << endl;
affiche 3.
3
a
p
p = &a;
a
*p = 5;
Rsum
Un pointeur est une variable. On dclare un pointeur en mettant une
toile (*) entre le type et le nom du pointeur:
int * p;
Un pointeur contient une adresse.
On peut obtenir l'adresse d'une variable avec l'oprateur &:
int a = 0;
p = &a;
L'oprateur * permet d'accder la mmoire pointe par un pointeur:
int b = *p;
*p = 1;
0
b
Le pointeur NULL ou 0
On utilise parfois la valeur 0, ou la constante NULL (de type pointeur, qui vaut
0) pour initialiser un pointeur:
int * p = 0;
ou
int * p = NULL;
L'adresse 0 n'est jamais utilise pour stocker des variables, elle correspond
donc toujours une adresse invalide: Si on essaie d'accder la valeur
pointe par p en faisant par exemple:
int * p = 0;
int a = *p;
*p = 12;
on provoque un:
Segmentation fault
L'intrt du pointeur NULL est par exemple de signaler qu'une fonction n'a
pas pu fonctionner correctement, ou qu'un pointeur ne contient pas une
adresse valide.
Remarques
On peut voir l'oprateur * comme l'inverse de l'oprateur &:
b = *(&a);
est quivalent
b = a;
Affectation de pointeurs
On peut affecter un pointeur la valeur d'un autre pointeur de mme
type.
Exemple:
int n(1), p(2);
int * ad1, * ad2;
Que font les instructions:
ad1 = &n;
ad2 = &p;
*ad1 = *ad2 + 3;
ad1 = ad2;
*ad1 = *ad2 + 5;
ad1
ad2
Pas--pas
1
ad1
ad2
Pas--pas
1
ad1
ad2
Pas--pas
1
ad1
ad2
Pas--pas
15
ad1
ad2
exactement comme n = p + 3;
n contient maintenant 5
Pas--pas
5
ad1
ad2
Pas--pas
5
ad1
ad2
Pas--pas
5
ad1
ad2
exactement comme p = p + 5;
p contient donc maintenant 7
Exercice
int a(2), b(5);
int * p;
p = &a;
cout << a << " " << *p << endl;
a = a + 1;
cout << a << " " << *p << endl;
*p = b;
cout << a << " " << *p << endl;
b = b + 1;
cout << a << " " << *p << endl;
Rappel
Si on excute:
void mis_a_zero(int a)
{
a = 0;
}
int main()
{
int n = 10;
mis_a_zero(n);
}
on obtient:
apres appel: n = 10
La fonction mis_a_zero ne peut pas changer la valeur de n !
Pas--pas
void mis_a_zero(int a)
{
a = 0;
}
int main()
{
int n = 10;
cout << "avant appel: n = " << n << endl;
mis_a_zero(n);
cout << "apres appel: n = " << n << endl;
}
10
n
Pas--pas
10
a
void mis_a_zero(int a)
{
a = 0;
}
int main()
{
int n = 10;
cout << "avant appel: n = " << n << endl;
mis_a_zero(n);
cout << "apres appel: n = " << n << endl;
}
10
n
Pas--pas
10
a
void mis_a_zero(int a)
{
a = 0;
}
int main()
{
int n = 10;
cout << "avant appel: n = " << n << endl;
mis_a_zero(n);
cout << "apres appel: n = " << n << endl;
}
10
n
Pas--pas
0
a
void mis_a_zero(int a)
{
a = 0;
}
int main()
{
int n = 10;
cout << "avant appel: n = " << n << endl;
mis_a_zero(n);
cout << "apres appel: n = " << n << endl;
}
10
n
Pas--pas
void mis_a_zero(int a)
{
a = 0;
}
10
int main()
{
int n = 10;
Pas--pas
void mis_a_zero(int * pa)
{
*pa = 0;
}
10
int main()
{
int n = 10;
mis_a_zero(&n);
}
n
1. La variable n est cre en mmoire
Pas--pas
void mis_a_zero(int * pa)
{
*pa = 0;
}
10
int main()
{
int n = 10;
mis_a_zero(&n);
}
n
2. L'adresse de la variable n est passe en paramtre.
Pas--pas
void mis_a_zero(int * pa)
{
*pa = 0;
}
pa
int main()
{
int n = 10;
mis_a_zero(&n);
}
10
n
Pas--pas
void mis_a_zero(int * pa)
{
*pa = 0;
}
pa
int main()
{
int n = 10;
mis_a_zero(&n);
}
10 0
Pas--pas
void mis_a_zero(int * pa)
{
*pa = 0;
}
int main()
{
int n = 10;
mis_a_zero(&n);
}
int main()
{
int n = 10;
mis_a_zero(&n);
}
Exercice
void f(int * p, int q)
{
*p = *p + q;
}
void g(int * r)
{
f(r, 1);
}
int a = 0, b = 2;
f(&a, b);
cout << a << " " << b << endl;
g(&a);
cout << a << " " << b << endl;
Tableaux et pointeurs
Utilis seul, le nom du tableau correspond l'adresse du premier
lment.
Par exemple, on peut faire:
int T[5];
int * tab = T;
tab
adresse
contenu
19996
T = 20000
T[0]
20004
T[1]
20008
T[2]
20012
T[3]
20016
T[4]
20020
Tableaux et pointeurs
Aprs:
tab
int T[5];
int * tab = T;
tab pointe sur le premier lment de T.
*tab correspond donc T[0], le premier lment de T.
tab + 1 est l'adresse du deuxime lment de T.
*(tab + 1) correspond donc T[1], le deuxime
lment de T.
etc...
adresse
contenu
19996
T = 20000
T[0]
20004
T[1]
20008
T[2]
20012
T[3]
20016
T[4]
20020
Notez que:
Si
tab vaut 20000,
et si tab est un pointeur sur int
Alors
tab + 1 vaut 20004
pour pointer sur le int suivant: un int est reprsent sur 4 octets, et les adresses
sont dfinies en octet.
Ce mcanisme de calcul simplifie l'accs aux lments du tableau: il n'y a pas savoir
qu'il faut multiplier par 4 dans le cas des int, par 8 dans le cas des double, etc...
Tableaux et pointeurs
Aprs:
int T[5];
int * tab = T;
tab pointe sur le premier lment de T.
*tab correspond donc T[0], le premier lment de T.
tab
adresse
contenu
19996
T = 20000
T[0]
20004
T[1]
20008
T[2]
20012
T[3]
T[4]
tab
adresse
contenu
19996
T = 20000
T[0]
20004
T[1]
20008
T[2]
20012
T[3]
20016
T[4]
20020
adresse
contenu
19996
int T[5];
ajoute1_aux_elements(T);
T = 20000
T[0]
20004
T[1]
20008
T[2]
20012
T[3]
20016
T[4]
20020
tab
adresse
contenu
19996
int T[5];
ajoute1_aux_elements(T);
T = 20000
T[0]
20004
T[1]
20008
T[2]
20012
T[3]
20016
T[4]
20020
0
i
tab
adresse
contenu
19996
int T[5];
ajoute1_aux_elements(T);
T = 20000
T[0]
20004
T[1]
20008
T[2]
20012
T[3]
20016
T[4]
20020
tab
adresse
contenu
19996
int T[5];
ajoute1_aux_elements(T);
T = 20000
T[0]
20004
T[1]
20008
T[2]
20012
T[3]
20016
T[4]
20020
tab
adresse
contenu
19996
int T[5];
ajoute1_aux_elements(T);
T = 20000
T[0]
20004
T[1]
20008
T[2]
20012
T[3]
20016
T[4]
20020
Exercice
Allocation dynamique:
Allouer de la mmoire
pendant l'excution du programme
Allouer de la mmoire
pendant l'excution du programme
On peut allouer de la mmoire pendant l'excution du programme.
On parle d'Allocation dynamique.
L'allocation se fait avec l'instruction new.
Une fois que la mmoire alloue n'est plus utile, IL FAUT la librer,
avec l'instruction delete.
Allouer de la mmoire
pendant l'excution du programme
int * tab;
tab = new int[5];
tab
mmoire
Allouer de la mmoire
pendant l'excution du programme
int * tab;
tab = new int[5];
tab
mmoire
Allouer de la mmoire
pendant l'excution du programme
int * tab;
tab = new int[5];
tab
tab[2] = 10;
tab[3] = 5 * tab[2];
delete [] tab;
L'instruction delete libre la mmoire alloue
par new, c'est--dire que cette partie de la
mmoire va pouvoir tre utilise par d'autres
programmes.
Le programme n'a plus le droit d'accder
cette partie de la mmoire.
mmoire
new et delete
Allocation de la mmoire:
Libration de la mmoire:
delete []
tab;
new et delete
Nombre d'lments allouer
Allocation de la mmoire:
Libration de la mmoire:
Adresse de dbut de
la mmoire librer
delete []
Attention ne pas
oublier les crochets [ ]
tab;
du
L'expression
new int[nb_elements] est
un pointeur sur int
return resultat;
Exemple d'utilisation:
int * T = cree_tableau_aleatoire(5, 100);
return resultat;
100
return resultat;
100
return resultat;
mmoire
?
?
?
?
?
100
return resultat;
resultat
mmoire
?
?
?
?
?
100
return resultat;
resultat
mmoire
56
34
82
17
39
100
return resultat;
resultat
mmoire
56
34
82
17
39
return resultat;
mmoire
56
34
82
17
39
return resultat;
mmoire
56
34
82
17
39
resultat
return resultat;
mmoire
56
34
82
17
39
resultat
Allocation dynamique de
structures
...
delete c;
nom
0.0
poids
nom
0.0
poids
(*c).poids = 2.5;
nom
2.5
poids
L'oprateur ->
La notation
(*c).poids
n'est pas trs lisible.
Il existe un oprateur, not -> (un signe moins -, un signe suprieur
>), qui permet d'crire des expressions quivalentes mais plus lisibles:
c->poids
. ou -> ?
A gauche de . on trouve forcment une variable de type structure:
Chat c;
c.poids = 2.5;
Messages d'erreur
A la compilation de:
Chat c;
c->poids = 2.5; // !!
on obtient l'erreur:
error: base operand of `->' has non-pointer type `Chat'
c n'est pas un pointeur et appliquer l'oprateur -> sur c n'a donc pas de sens.
A la compilation de:
Chat * pc;
pc.poids = 2.5; // !!
on obtient l'erreur:
error: request for member `poids' in `pc', which is of non-class
type `Chat*'
L'oprateur . s'applique sur une structure, pas un pointeur comme pc est ici.
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 2.5);
"Felix"
2.5
"Felix"
2.5
c
2.5
"Felix"
nom
0.0
return c;
}
poids
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 2.5);
c
2.5
"Felix"
nom
f
0.0
return c;
}
poids
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 2.5);
c
2.5
"Felix"
nom
f
2.5
return c;
}
poids
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 2.5);
c
2.5
"Felix"
nom
f
2.5
return c;
}
poids
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 2.5);
nom
f
2.5
return c;
}
poids
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 2.5);
nom
f
2.5
return c;
}
poids
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 2.5);
nom
0.0
poids
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);
nom
0.0
poids
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);
chat
void demande_poids(Chat * chat)
{
cout << "Entrez le poids de " << chat->nom << endl;
cin >> chat->poids;
}
nom
0.0
poids
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);
chat
void demande_poids(Chat * chat)
{
cout << "Entrez le poids de " << chat->nom << endl;
cin >> chat->poids;
}
nom
0.0
poids
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);
chat
void demande_poids(Chat * chat)
{
cout << "Entrez le poids de " << chat->nom << endl;
cin >> chat->poids;
}
nom
0.0
poids
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);
chat
void demande_poids(Chat * chat)
{
cout << "Entrez le poids de " << chat->nom << endl;
cin >> chat->poids;
}
nom
2.5
poids
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);
nom
2.5
poids
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);
nom
?
poids
g2
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);
nom
?
poids
g2
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);
nom
?
poids
g2
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);
chat
void demande_poids(Chat * chat)
{
cout << "Entrez le poids de " << chat->nom << endl;
cin >> chat->poids;
}
nom
?
poids
g2
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);
chat
void demande_poids(Chat * chat)
{
cout << "Entrez le poids de " << chat->nom << endl;
cin >> chat->poids;
}
nom
?
poids
g2
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);
chat
void demande_poids(Chat * chat)
{
cout << "Entrez le poids de " << chat->nom << endl;
cin >> chat->poids;
}
nom
?
poids
g2
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);
chat
void demande_poids(Chat * chat)
{
cout << "Entrez le poids de " << chat->nom << endl;
cin >> chat->poids;
}
nom
3.2
poids
g2
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);
chat
void demande_poids(Chat * chat)
{
cout << "Entrez le poids de " << chat->nom << endl;
cin >> chat->poids;
}
nom
3.2
poids
g2
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);
nom
3.2
poids
g2
Exemple d'utilisation:
Chat * g = cree_chat("Felix", 0.0);
demande_poids(g);
Chat g2;
g2.nom = "Garfield";
demande_poids(&g2);