Module: ALGORITHMIQUE 1
Chapitre 9: Les pointeurs
Niveaux: 1A
Equipe ALGO
Année universitaire:
2022/2023
1
Objectifs Spécifiques
A la fin de ce chapitre, l’étudiant sera capable de :
Comprendre le type pointeur
Manipuler une variable à partir de son adresse
Utiliser un pointeur en paramètre d’une fonction
Utiliser un pointeur dans l’allocation dynamique.
2
Problématique 1
Supposons que votre enseignant a corrigé votre copie d’examen et a
sauvegardé la note sous drive. S’il te rend la copie et tu modifies la note est
ce que la note originale change ?
Solution
Pour changer la valeur nous devons accéder à l’adresse ou se
trouve les notes au lieu d’avoir une copie sur cette valeur
Pareil si vous souhaitez changer la valeur d’une variable
à travers une fonction, vous devez passez son adresse au
lieu de sa valeur!
Cette adresse sera stockée dans une
variable de type pointeur.
Problématique 2
Supposons que je veux allouer un tableau d’entier en mémoire sachant que
je ne connais pas sa taille à l’avance allouer avec une taille maximale
Il se peut que pendant l’exécution, l’utilisateur choisit une taille qui dépasse
cette taille maximale. Que devons nous faire ?
Solution
Selon le besoin de l’utilisateur en utilisant l’allocation
dynamique!
Ceci en utilisant un pointeur.
PARTIE I
Définition et manipulation d’un pointeur
7
Définition
Un pointeur est une variable qui peut contenir l’adresse d’un espace mémoire
alloué ou l’adresse d’une autre variable.
Chaque pointeur est limité à un type de donnée
Si un pointeur P contient l’adresse d’une variable A , on dit que P pointe vers A.
Adressage Directe
L’adressage directe consiste à accéder à la valeur d’une variable à travers son nom
(identificateur)
x
Exemple:
x: entier 0
x← 0
…. H004 H008 H016 ….
Adressage Indirecte
L’adressage indirecte consiste à accéder à la valeur d’une variable en passant par un pointeur
contenant l’adresse de la variable.
X P
Exemple:
0 H008
X: entier
X← 0 …. H004 H008 H016 H020
P: pointeur sur un entier contenant
l’adresse de X
Syntaxe de déclaration
Il existe 2 conventions pour déclarer une variable de type pointeur:
• 1ère convention: <nom_pointeur>: pointeur sur <type>
-Exemple: P: pointeur sur entier
• 2ème convention: <nom_pointeur>: * <type>
-Exemple: P: *entier
Remarque:
Un pointeur qui ne contient aucune adresse doit être initialisé à NULL( Not Identified
Link), sinon il va pointer n’importe ou!
Opérateurs de base
Opérateur « adresse de »: &
L’opérateur & permet de récupérer l’adresse d’une variable
• Syntaxe: &<nom_variable>: fournit l’adresse de la variable <nom_variable>
Exemple: X P
VARIABLE
P: pointeur sur entier
X:entier
0 H008
P ← &X …. H004 H008 H016 H020
Adresse de X
Opérateurs de base
Opérateur « contenu de »: *
Avant d’accéder au contenu,
L’opérateur * permet de récupérer le contenu d’une variable il faut s’assurer que le
pointeur est différent de
NULL!
• Syntaxe: *<nom_pointeur>: fournit le contenu du pointeur <nom_pointeur>
X P
Exemple:
VARIABLE
P: pointeur sur entier
X:entier 0 H008
…. H004 H008 H016 H020
P ← &X
(*P) est le contenu de la variable sur laquelle pointe p: 0
Adresse de X
Opérateurs de base
Etat initial des variables
Algorithme Exemple1
Variables
A,B: entier
p:*entier
Debut
(*Etat initial des variables*)
A ← 10 Après modification des variables
B ← 50
(*Modification des variables*)
p ←&A
B ←*p
*p←20
Fin
PARTIE I
Pointeurs et Tableaux
15
Pointeur et Tableau
Un tableau est un pointeur statique contenant l’adresse d’un espace mémoire
contiguë qui est aussi l’adresse du premier élément du tableau.
C’est à dire les 2 écritures suivantes sont équivalentes:
T=&T[1]
Remarque:
Vous n’avez pas le droit de changer la valeur d’un tableau statique: T ←T2
T T[1] T[2]
Exemple:
T: tableau de 2 entiers
T[1] ← 0
T[2] ← 1 H008 0 1
…. H004 H008 H016 H020
Pointeur et Tableau
Etant donné que les éléments d’un tableau sont allouées de manière contigüe :
• Les adresses des éléments sont identifiées par : T, T+1, T+2, … T+N-1
• Les valeurs des éléments sont identifiées par : *T, *(T+1), *(T+2), ..., *(T+N-1)
T T[1] T[2]
H008 0 1
…. H004 H008 H012 H016
Exercice d’application 1
Utiliser l’opérateur (*) pour remplir un tableau d’entiers comme le montre l’exemple
suivant:
1 2 3 4 5
Algorithme 1 Algorithme 2
T: tableau [1..50] d’entier T: tableau [1..50] d’entier
n , i: entier n , i: entier
p: pointeur sur entier
Pour i de 1 à n Faire i ←1
*(T+i-1) ← i Pour p de T à T+n-1 Faire
Fin Pour *p ← i
i ←i+1
Fin Pour
Exercice d’application 2
Afficher la valeur de chaque expression sachant que T est un tableau de 3 entiers
T H004
T+1 H008
*T 2 2 0 1 … H004
*(T+1) 0
…. H004 H008 H016 H020
&T[2] H008
T+2 H016
PARTIE I: Pointeurs et
Fonctions/Procédures
20
Quelques contraintes
Une fonction est un sous programme permettant de faire un traitement et de retourner
un résultat unique. Comment faire pour retourner plusieurs résultats ?
Il n’y a qu’une solution pour retourner plusieurs résultats: passer en paramètre
l’adresse des variables où seront stockés les résultats.
Supposons que nous souhaitons modifier la valeur d’une variable passée en paramètre
à une fonction. Comment faire?
Le passage par adresse est utilisé pour modifier le contenu des variables déclarées
dans d’autres fonctions.
Passage de paramètre par valeur
Ecrire la procédure permute permettant de permuter 2 entiers:
Passage de paramètre par valeur
Lors de l’appel, les valeurs de x et y sont copiées dans les paramètres u et v de
la procédure « permute »
« permute » échange bien le contenu des variables locales u et v, mais les
valeurs de x et y restent les mêmes
Pour changer la valeur d’une variable de la fonction appelante, nous allons
procéder comme suit :
a. Le programme appelant doit fournir l’adresse de la variable
b. La fonction appelée doit déclarer le paramètre comme pointeur.
Passage de paramètre par adresse
Ecrire la procédure permute permettant de permuter 2 entiers:
Passage de paramètre par adresse
Lors de l’appel, les adresses de x et y sont copiées dans les pointeurs
de u et v, respectivement
« permute » échange ensuite le contenu des adresses indiquées par les
pointeurs u et v
A partir du moment où une variable est considérée comme un
pointeur, toute affectation de cette variable se traduit
automatiquement par la modification de la variable sur laquelle elle
pointe
Exercice d’application 3
Ecrire une procédure MaxMin permettant de retourner le minimum et le
maximum dans un tableau d’entiers:
Algorithme Metrique Pour i de 2 à n Faire
Constante Nmax=50 Si (T[i]>(*max)) alors (*max) ← T[i]
Type Sinon si (T[i]<(*min)) alors (*min) ← T[i]
Tab:tableau [1.. Nmax]d’entiers Fin si
Variable Fin Pour
n,max,min:entier Fin
T:Tab
Procédure MaxMin(max,min:pointeur sur entier, Début
n:entier, T:Tab) Lire(n)
Variable Remplir(T,n)
i:entier MaxMin(&max, &min,n,T)
Début Ecrire(‘’Le Max et le Min sont: ’’,max,min)
(*min) ← T[1]
(*max) ← T[1] Fin
PARTIE II: Pointeurs et
Enregistrement
27
Pointeur et enregistrement
Un pointeur peut aussi contenir l’adresse d’un enregistrement
Pour accéder à un élément de l’enregistrement à travers
un pointeur, on utilise une des syntaxes suivantes:
(*nomPointeur).champ
nomPointeur →champ
Exercice d’application 4
Ecrire une procédure saisir permettant de saisir les informations d’un étudiant:
Algorithme Etudiant
Type
Etudiant=Enregistrement
NumeroIncription: entier
Nom, Prenom: chaine[10]
FinEnregistrement
Variable
Et : Etudiant
Procédure saisir(p:pointeur sur étudiant)
Début
Lire(p→NumeroInscription)
Lire(p→Nom)
Lire(p→Prénom)
Fin
Début
Saisir(&ET)
Ecrire(ET)
Fin
PARTIE II: Allocation
Dynamique
30
Allocation statique
Les variables créées de manière statique sont allouées et libérées
automatiquement par le système d'exploitation. L'espace à allouer est connu
durant la phase de compilation.
Exemple 1: supposons qu’on a déclaré un tableau de 20 Etudiants, Comment
faire pour ajouter l’étudiant numéro 21?
Exemple 2: pour une application qui permet de gérer 20 employés, le
développeur a déclaré un tableau d’employés de taille 100
Pas d’optimisation Allocation dynamique
de la mémoire selon le besoin
Allocation dynamique
L’allocation dynamique permet de réserver un espace mémoire de taille
variable en milieu d’exécution d’un programme
Ainsi, la taille de l’espace n’est pas connue à l’avance.
La libération d’un espace mémoire alloué dynamiquement n’est pas
automatique comme dans l’allocation statique.
L’allocation dynamique ne se fait qu’à travers des pointeurs.
Allocation dynamique
Allouer(nbOctets): <type*> : permet d’allouer dynamiquement nb octets.
Cette fonction retourne:
- NULL: S’il n’y a pas assez d’espace mémoire
- l’adresse de l’espace allouée, sinon
Remarque: pour connaitre le nombre d’octets d’un type donné, utilisez la
fonction: taille(<type>): entier
Exemple:
Variable
P: *entier
Début
P ← allouer(taille(entier))
Fin
Allocation dynamique et libération
Libérer(<type> *) : permet de libérer un espace mémoire allouée
dynamiquement avec la fonction « allouer »
Exemple:
libérer(P)
Attention: Si on ne libère pas la mémoire, elle risque d’être saturée et le
programme peut se planter.
Exercice d’application 5
Ecrire un algorithme permettant de réserver et saisir n entiers alloués dynamiquement
Algorithme Exemple
Variable
T:pointeur sur entier
n,i:entier
Début
Lire(n)
T ← allouer(n*taille(entier))
Si (T=NULL) alors Ecrire(‘’ espace mémoire insuffisant ’’)
Sinon
Pour i de 1 à n faire
Lire(T[i])
FinPour
(* Si vous n’avez plus besoin de l’espace réservé il faut le libérer *)
Libérer(T)
FinSI
Fin
Exercice d’application 6
Ecrire une fonction qui permet de remplir un tableau de n étudiants alloué dynamiquement et le retourne.
Fonction RemplirEtudiant (n : entier) : *Etudiant
Variable
i :entier
T : *Etudiant
Début
T ← allouer (n*taille(Etudiant))
Si (T<>NUUL) alors
Pour i allant de 1 à n faire
lire(T[i].CIN, T[i]. nom, T[i].prenom)
Fin pour
Sinon
Ecrire(‘’ espace mémoire insuffisant ’’)
FinSi
RemplirEtudiant ← T
Fin
Récapitulons
Un pointeur est utilisé pour:
- Stocker l’adresse d’une variable
- Modifier la valeur d’une variable à travers une fonction
- Allouer une variable dynamiquement
Un pointeur peut être initialisé de 3 différentes manière à:
- La constante NULL: s’il ne pointe vers rien
- L’adresse d’une variable
- L’adresse d’un espace mémoire allouée dynamiquement avec la fonction
allouer