Vous êtes sur la page 1sur 46

Cours de Programmation 2

(Programmation C et structures de données)


Récursivité terminale et non terminale - Pile d’appel
Pointeurs (1re partie)

Christophe Tollu
(Première version des diapos par Julien David)

A209 (poste 3691) - ct@lipn.univ-paris13.fr

24 janvier 2023

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 1 / 33
F`o“n`cˇtˇi`o“n¯s ˚r`é´cˇu˚r¯sfi˚i‹vfle˙s

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 2 / 33
Fonctions récursives

Définitions
Une fonction récursive est une fonction qui, dans sa définition, contient
un appel à elle-même.
Un appel récursif est un appel réalisé alors que l’exécution d’un appel
précédent de la même fonction n’est pas achevé.

Exemple de fonction récursive


1 i n t so m m e p r e mi er s e nt ie r s ( unsigned i n t n )
2 {
3 unsigned i n t r e s ;
4 i f ( 0 == n )
5 return 0;
6 else
7 r e t u r n n + s om me p r e mi er s e n t i e r s ( n−1);
8 }

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 3 / 33
Deux exemples très classiques

Calcul de la factorielle d’un entier positif


1 unsigned f a c t ( unsigned n )
2 {
3 i f ( 0 == n ) r e t u r n 1 ;
4 r e t u r n n ∗ f a c t ( n−1);
5 }

Calcul du ne terme de la suite de Fibonacci


1 unsigned i n t f i b ( unsigned i n t n )
2 {
3 i f ( 0 == n | | 1 == n )
4 return n;
5 r e t u r n f i b ( n−1) + f i b ( n−2);
6 }

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 4 / 33
Récursivité : terminaison
Empilement potentiellement infini des appels récursifs
1 int f ( int n)
2 { r e t u r n f ( n−1);}

Conditions d’arrêt et terminaison


Il faut soigneusement identifier les conditions d’arrêt...
...et s’assurer que pour tout appel, ces conditions d’arrêt seront
satisfaites après un nombre fini d’appels récursifs.

Un exemple plus compliqué à analyser


1 unsigned i n t ack ( i n t m, i n t n )
2 {
3 i f ( 0 == m)
4 return n + 1;
5 i f ( 0 == n )
6 r e t u r n ack (m−1, 1 ) ;
7 r e t u r n ack (m−1, ack (m, n − 1 ) ) ;
8 }

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 5 / 33
Récursivité terminale / non terminale

Définitions
Un appel récursif est non terminal s’il est utilisé comme sous-expression
stricte d’une expression évaluée dans l’appel “parent” de la (même)
fonction. [cf. fonction somme premiers entiers]
Un appel récursif est terminal si son résultat est celui de l’appel “parent”
de la (même) fonction [cf. fonction pgcd] .
Une fonction récursive est (à récursivité) terminale si tous ses appels
récursifs sont terminaux.

Exemple (fonction récursive terminale)


1 unsigned i n t pgcd ( unsigned i n t m, unsigned i n t n )
2 { / ∗ on suppose que m e t n s o n t s t r i c t e m e n t s p o s i t i f s ∗ /
3 i f ( 0 == m % n ) / ∗ s i n d i v i s e m ∗ /
4 return n;
5 else
6 r e t u r n pgcd ( n , m % n ) ;
7 }

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 6 / 33
Récursivité terminale / non terminale

Optimisation possible
Dans le cas d’une récursivité terminale, il n’est (théoriquement) pas
nécessaire d’empiler les appels : l’appel récursif ”remplace”
simplement l’appel parent sur la pile (en passant les nouvelles valeurs
des arguments et en conservant l’adresse de retour de l’appel initial).
Le compilateur, dans certains contextes d’optimisation, peut donc traiter
une fonction récursive comme une fonction itérative et optimiser la
gestion de la pile (tail-call optimization).
L’option -O2 du compilateur gcc active ce niveau d’optimisation (sans
aucune garantie que les fonctions récursives qui peuvent être ainsi
”dérécursivées” le seront effectivement).

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 7 / 33
Factorielle non terminale et terminale

Factorielle non terminale


1 unsigned f a c t ( unsigned n )
2 {
3 i f ( 0 == n ) r e t u r n 1 ;
4 r e t u r n n ∗ f a c t ( n−1);
5 }

Factorielle terminale
1 unsigned f a c t 2 t e r ( unsigned n , unsigned acc )
2 {
3 i f ( n <= 0 )
4 r e t u r n acc ;
5 r e t u r n f a c t 2 t e r ( n−1, n∗acc ) ;
6 }
7
8 unsigned f a c t t e r ( unsigned n )
9 {
10 return fact2 ter (n , 1);
11 }

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 8 / 33
Récursivité et tableaux

Recherche dans un tableau de flottants trié


1 / ∗ ∗ Renvoie l ’ i n d i c e d ’ une v a l e u r du t a b l e a u egale a x ∗ /
2 / ∗ s i une t e l l e v a l e u r e x i s t e , r e n v o i e −1 s i n o n ∗ /
3 i n t r e c h e r c h e t a b ( f l o a t x , f l o a t ∗ tab , i n t deb , i n t f i n )
4 {
5 i n t m i l i e u = ( deb + f i n ) / 2 ;
6 i f ( f i n < deb )
7 r e t u r n −1;
8 i f ( x < tab [ m i l i e u ] )
9 r e t u r n r e c h e r c h e t a b ( x , tab , deb , m i l i e u − 1 ) ;
10 i f ( x > tab [ m i l i e u ] )
11 r e t u r n r e c h e r c h e t a b ( x , tab , m i l i e u + 1 , f i n ) ;
12 return milieu ;
13 }

L’appel initial pourrait être...


1 / ∗ En supposant que t e s t un t a b l e a u de f l o t t a n t s ∗ /
2 / ∗ de t a i l l e au moins n e t dont l e s v a l e u r s s o n t rangees dans l ’ o r d r e c r o i s s a n t ∗ /
3 i n t r e s u l t = r e c h e r c h e t a b ( −0.75 , t , 0 , n−1);

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 9 / 33
Récursivité et efficacité

Appels récursifs redondants


1 unsigned i n t f i b ( unsigned i n t n )
2 {
3 i f ( 0 == n | | 1 == n )
4 return n;
5 r e t u r n f i b ( n−1) + f i b ( n−2);
6 }

Pour exécuter l’appel f(20), on exécutera plus de trois mille trois cents appels
f(2) !

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 10 / 33
Récursivité et efficacité : mémoı̈sation

Fibonacci  mémoı̈sé 
1 # d e f i n e N 50
2 unsigned f i b t a b [N] = {0};
3
4 unsigned fib mem ( unsigned f i b t a b [ ] , unsigned n )
5 {
6 i f ( 0 == n | | 1 == n )
7 return ( fib tab [n] = n ) ;
8 i f ( 0 == f i b t a b [ n ] )
9 f i b t a b [ n ] = fib mem ( f i b t a b , n−1) + fib mem ( f i b t a b , n−2);
10 return fib tab [n ] ;
11 }

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 11 / 33
Récursivité et efficacité : récursivité terminale

Fibonacci récursif terminal


1 unsigned f i b 2 t e r ( unsigned n , unsigned a , unsigned b )
2 {
3 i f ( 0 == n )
4 return a;
5 i f ( 1 == n )
6 return b;
7 r e t u r n f i b 2 t e r ( n−1, b , a+b ) ;
8 }
9
10 unsigned f i b t e r ( unsigned n )
11 {
12 fib2 ter (n, 0, 1);
13 }

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 12 / 33
Récursivité et efficacité

Récursif vs itératif
Il existe des techniques pour remédier à la redondance des appels dans
une fonction récursive.
Il ne faut donc pas croire que l’exécution d’une fonction récursive est
toujours nettement plus coûteuse que celle d’une fonction itérative
effectuant la même tâche !
En outre, l’écriture d’une fonction récursive est, dans de nombreuses
applications, beaucoup plus  naturelle  . . .

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 13 / 33
Récursivité et efficacité
TD 1 exercice 1 (version itérative Θ(n2 ))
1 i t e m m a x d i f f t a b ( i t e m t [ ] , i n t deb , i n t f i n ) {
2 int i , j ;
3 item res = 0;
4 f o r ( i = deb ; i <= f i n ; ++ i )
5 f o r ( j = i +1; j <= f i n ; ++ j )
6 i f ( t [ j ]− t [ i ] > r e s )
7 r e s = t [ j ]− t [ i ] ;
8 r e t u r n res ;
9 }

TD 1 exercice 1 (version récursive Θ(n log2 n))


1 i t e m m a x d i f f t a b r e c ( i t e m t [ ] , i n t deb , i n t f i n ) {
2 i n t m = ( deb+ f i n ) / 2 ;
3 i t e m m a x f i n min deb , m a x d i f f d e b , m a x d i f f f i n ;
4 i f ( f i n <= deb )
5 return 0;
6 m a x d i f f d e b = m a x d i f f t a b r e c ( t , deb , m) ;
7 m a x d i f f f i n = m a x d i f f t a b r e c ( t , m+1 , f i n ) ;
8 m a x f i n m i n d e b = max tab ( t , m+1 , f i n ) − m i n t a b ( t , deb , m) ;
9 r e t u r n max trois ( max diff deb , m a x d i f f f i n , max fin min deb ) ;
10 }
Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 14 / 33
Z`o“n`e˙s `d`e ”m`é›m`o˘i˚r`e

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 15 / 33
Zones de mémoire

Avertissement liminaire
La présentation de la mémoire qui suit est schématique. Elle ne vise
qu’à faciliter la compréhension des pointeurs (et plus tard de l’allocation
dynamique).
Pour plus de détails sur l’organisation de la mémoire, les modes
d’allocation, la correspondance adresses virtuelles – adresses
physiques, etc., il faudra attendre un cours sur l’architecture des
machines et les systèmes d’exploitation.

En première approximation...
la mémoire peut être représentée comme un (long) tableau d’octets
segmenté en plusieurs zones.

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 16 / 33
Zones de mémoire

Pile d’appel Variables locales, paramètres d’entrée des fonctions, adresse de retour,

Espace “libre”

Tas Allocation dynamique

Zone de données Variables globales et statiques

Zone texte Instructions des fonctions

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 17 / 33
Zone texte et zone de données

Rappel
Un fichier exécutable contient déjà :
Une zone correspondant aux variables globales et statiques.
Une zone correspondant à l’ensemble des fonctions du programme.

Au lancement de l’exécution du programme


Les (instructions des) fonctions sont chargées en mémoire dans la zone
texte.
Chaque instruction de chaque fonction possède une adresse propre en
mémoire.

Zone texte
Cette zone est en lecture seule.
Sa taille est déterminée avant l’exécution.

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 18 / 33
Zone texte et zone de données

Rappel
Un fichier exécutable contient déjà :
Une zone correspondant aux variables globales et statiques.
Une zone correspondant à l’ensemble des fonctions du programme.

Au lancement de l’exécution du programme


Les (instructions des) fonctions sont chargées en mémoire dans la zone
texte.
Chaque instruction de chaque fonction possède une adresse propre en
mémoire.

Zone texte
Cette zone est en lecture seule.
Sa taille est déterminée avant l’exécution.

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 18 / 33
Zone texte et zone de données

Rappel
Un fichier exécutable contient déjà :
Une zone correspondant aux variables globales et statiques.
Une zone correspondant à l’ensemble des fonctions du programme.

Au lancement de l’exécution du programme


Les (instructions des) fonctions sont chargées en mémoire dans la zone
texte.
Chaque instruction de chaque fonction possède une adresse propre en
mémoire.

Zone texte
Cette zone est en lecture seule.
Sa taille est déterminée avant l’exécution.

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 18 / 33
Zone texte et zone de données

Au lancement de l’exécution du programme


La zone de données de l’exécutable est recopiée dans la mémoire.
Tous les objets globaux et statiques ont une adresse fixée avant
l’exécution.

Zone de données
Cette zone peut être en lecture seule ou en lecture–écriture.
La taille de cette zone (et de chaque objet global ou statique) est
déterminée avant l’exécution..

Accessibilité
Les variables dans la zone de données et les fonctions dans la zone texte
sont accessibles depuis tout point du programme (ou depuis tout point
d’un segment correspondant à un fichier objet pour les objets statiques).

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 19 / 33
Zone texte et zone de données

Au lancement de l’exécution du programme


La zone de données de l’exécutable est recopiée dans la mémoire.
Tous les objets globaux et statiques ont une adresse fixée avant
l’exécution.

Zone de données
Cette zone peut être en lecture seule ou en lecture–écriture.
La taille de cette zone (et de chaque objet global ou statique) est
déterminée avant l’exécution..

Accessibilité
Les variables dans la zone de données et les fonctions dans la zone texte
sont accessibles depuis tout point du programme (ou depuis tout point
d’un segment correspondant à un fichier objet pour les objets statiques).

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 19 / 33
Zone texte et zone de données

Au lancement de l’exécution du programme


La zone de données de l’exécutable est recopiée dans la mémoire.
Tous les objets globaux et statiques ont une adresse fixée avant
l’exécution.

Zone de données
Cette zone peut être en lecture seule ou en lecture–écriture.
La taille de cette zone (et de chaque objet global ou statique) est
déterminée avant l’exécution..

Accessibilité
Les variables dans la zone de données et les fonctions dans la zone texte
sont accessibles depuis tout point du programme (ou depuis tout point
d’un segment correspondant à un fichier objet pour les objets statiques).

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 19 / 33
Pile d’appel

Caractérisation
La pile d’appel permet de :
stocker les variables locales,
stocker les paramètres d’entrée des fonctions,
sauvegarder l’adresse de retour, la taille du segment actif de la pile (ou le
frame pointeur), . . . .

Précision
Dans ce cours on représente les appels de fonctions avec une zone
grisée dans la pile.
Cette zone grisée contient, entre autres, les informations permettant, à la
fin de l’exécution d’une fonction, de dépiler correctement en réactivant
la zone (frame) de l’appel précédent.
Le nombre et la nature des informations sauvegardées dans cette zone,
donc sa taille, dépendent de l’architecture.

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 20 / 33
Les limites de la pile d’appel

Limites
La taille de la pile
Les limites d’accès des variables locales

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 21 / 33
Les limites de la pile d’appel

La taille de la pile
La pile a une taille limitée.
À chaque appel de fonction, on ajoute des informations dans la pile.
Si un programme effectue trop d’appels imbriqués, la pile déborde.

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 22 / 33
Les limites de la pile d’appel

Les limites d’accès des variables locales


Avec nos connaissances actuelles :
Il n’est pas possible de modifier une variable locale d’une fonction A avec
une fonction B.
Il y a une  exception  à cette règle : on peut mettre à jour la valeur
d’une variable locale d’une fonction A par le résultat de la fonction B.

Exemple
Essayons d’écrire une fonction qui échange la valeur de deux variables.

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 23 / 33
1 v o i d swap ( i n t x , i n t y ){
2 i n t tmp=x ;
3 x=y ;
4 y=tmp ; y 7 996
5 }
6 i n t main ( ) {
7 i n t x =5; x 5 1000
8 i n t y =7;
9 swap ( x , y ) ; main
10 r e t u r n EXIT SUCCESS ;
11 }

tmp 5 968 tmp 5 968

y 7 972 y 5 972

x 5 976 x 7 976
y 7 996

swap(5,7) swap(5,7)
x 5 100

y 7 996 y 7 996
main

x 5 1000 x 5 1000

main main

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 24 / 33
1 v o i d swap ( i n t x , i n t y ){
2 i n t tmp=x ;
3 x=y ;
4 y=tmp ; y 7 996
5 }
6 i n t main ( ) {
7 i n t x =5; x 5 1000
8 i n t y =7;
9 swap ( x , y ) ; main
10 r e t u r n EXIT SUCCESS ;
11 }

tmp 5 968 tmp 5 968

y 7 972 y 5 972

x 5 976 x 7 976
y 7 996

swap(5,7) swap(5,7)
x 5 100

y 7 996 y 7 996
main

x 5 1000 x 5 1000

main main

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 24 / 33
1 v o i d swap ( i n t x , i n t y ){
2 i n t tmp=x ;
3 x=y ;
4 y=tmp ; y 7 996
5 }
6 i n t main ( ) {
7 i n t x =5; x 5 1000
8 i n t y =7;
9 swap ( x , y ) ; main
10 r e t u r n EXIT SUCCESS ;
11 }

tmp 5 968 tmp 5 968

y 7 972 y 5 972

x 5 976 x 7 976
y 7 996

swap(5,7) swap(5,7)
x 5 100

y 7 996 y 7 996
main

x 5 1000 x 5 1000

main main

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 24 / 33
1 v o i d swap ( i n t x , i n t y ){
2 i n t tmp=x ;
3 x=y ;
4 y=tmp ; y 7 996
5 }
6 i n t main ( ) {
7 i n t x =5; x 5 1000
8 i n t y =7;
9 swap ( x , y ) ; main
10 r e t u r n EXIT SUCCESS ;
11 }

tmp 5 968 tmp 5 968

y 7 972 y 5 972

x 5 976 x 7 976
y 7 996

swap(5,7) swap(5,7)
x 5 100

y 7 996 y 7 996
main

x 5 1000 x 5 1000

main main

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 24 / 33
Constat
Notre accès à la mémoire est pour l’instant très limité.
Une fonction ne peut accéder qu’à ses propres variables locales et
paramètres formels ou à des variables de la zone de données.

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 25 / 33
P̀o˘i‹n˚t´eˇu˚r¯s `eˇt `a`d˚r`e˙sfi¯sfi`e˙s
”m`é›m`o˘i˚r`e

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 26 / 33
Variables de type pointeur

Rappel
Une variable est caractérisée par :
son nom
son type
sa valeur
son adresse

Adresse d’une variable


Soit une variable int x; Pour désigner l’adresse de x, on écrit : &x.
Le signe &, appelé esperluette, désigne l’opérateur d’adressage.

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 27 / 33
Variables de type pointeur

Pointeurs : définition et terminologie


Une variable de type pointeur est une variable dont la valeur est une
adresse mémoire.
Si un pointeur contient l’adresse d’une variable, on dit qu’il pointe (sur,
vers) cette variable.
Le type d’un pointeur est le type des variables sur lesquelles il peut
pointer.

À quoi bon ?
En stockant l’adresse d’autres variables, on va pouvoir accéder à n’importe
quelle zone de la mémoire.

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 28 / 33
Variables de type pointeur

Pointeurs : définition et terminologie


Une variable de type pointeur est une variable dont la valeur est une
adresse mémoire.
Si un pointeur contient l’adresse d’une variable, on dit qu’il pointe (sur,
vers) cette variable.
Le type d’un pointeur est le type des variables sur lesquelles il peut
pointer.

À quoi bon ?
En stockant l’adresse d’autres variables, on va pouvoir accéder à n’importe
quelle zone de la mémoire.

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 28 / 33
Variables de type pointeur

Pointeurs : définition et terminologie


Une variable de type pointeur est une variable dont la valeur est une
adresse mémoire.
Si un pointeur contient l’adresse d’une variable, on dit qu’il pointe (sur,
vers) cette variable.
Le type d’un pointeur est le type des variables sur lesquelles il peut
pointer.

À quoi bon ?
En stockant l’adresse d’autres variables, on va pouvoir accéder à n’importe
quelle zone de la mémoire.

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 28 / 33
Variables de type pointeur

Déclaration
int * p;
Nom : p
Type : pointeur sur un entier (int *)
char * c;
Nom : c
Type : pointeur sur un caractère (char *)

Important ! Usage
Soit la déclaration int * z;
int* désigne le type de la variable z, à savoir pointeur vers int
*z désigne l’objet pointé par z (déréférencement de z)

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 29 / 33
Variables de type pointeur

1 i n t main ( ) {
2 i n t z =6; p 1000 996
3 i n t ∗ p=&z ;
4 p r i n t f ( ”%d\n ” ,∗ p ) ;
5 r e t u r n EXIT SUCCESS ; z 6 1000
6 }
main

Le programme affiche 6

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 30 / 33
Initialisation d’un pointeur

Initialisation
Comme toute variable, une variable de type pointeur doit être initialisée.
Si un pointeur n’est pas initialisé, il peut contenir une adresse
quelconque et modifier par erreur la case mémoire correspondante peut
avoir de graves conséquences.

Ne pointer vers rien


Soit un pointeur p. Pour que p ne pointe vers aucune case mémoire, on
écrit :
p=NULL;
Cette instruction est valable quel que soit le type du pointeur.

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 31 / 33
Pointeurs

Échange
On peut à présent réécrire la fonction swap

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 32 / 33
1 v o i d swap ( i n t ∗ x , i n t ∗ y ){
2 i n t tmp=∗x ;
3 ∗x=∗y ;
4 ∗y=tmp ; y 7 996
5 }
6 i n t main ( ) {
7 i n t x =5; x 5 1000
8 i n t y =7;
9 swap(& x ,& y ) ; main
10 r e t u r n EXIT SUCCESS ;
11 }

tmp 5 968 tmp 5 968

y 996 972 y 996 972

x 1000 976 x 1000 976


y 5 996

swap(1000,996) swap(1000,996)
x 7 1000

y 7 996 y 5 996
main

x 5 1000 x 7 1000

main main

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 33 / 33
1 v o i d swap ( i n t ∗ x , i n t ∗ y ){
2 i n t tmp=∗x ;
3 ∗x=∗y ;
4 ∗y=tmp ; y 7 996
5 }
6 i n t main ( ) {
7 i n t x =5; x 5 1000
8 i n t y =7;
9 swap(& x ,& y ) ; main
10 r e t u r n EXIT SUCCESS ;
11 }

tmp 5 968 tmp 5 968

y 996 972 y 996 972

x 1000 976 x 1000 976


y 5 996

swap(1000,996) swap(1000,996)
x 7 1000

y 7 996 y 5 996
main

x 5 1000 x 7 1000

main main

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 33 / 33
1 v o i d swap ( i n t ∗ x , i n t ∗ y ){
2 i n t tmp=∗x ;
3 ∗x=∗y ;
4 ∗y=tmp ; y 7 996
5 }
6 i n t main ( ) {
7 i n t x =5; x 5 1000
8 i n t y =7;
9 swap(& x ,& y ) ; main
10 r e t u r n EXIT SUCCESS ;
11 }

tmp 5 968 tmp 5 968

y 996 972 y 996 972

x 1000 976 x 1000 976


y 5 996

swap(1000,996) swap(1000,996)
x 7 1000

y 7 996 y 5 996
main

x 5 1000 x 7 1000

main main

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 33 / 33
1 v o i d swap ( i n t ∗ x , i n t ∗ y ){
2 i n t tmp=∗x ;
3 ∗x=∗y ;
4 ∗y=tmp ; y 7 996
5 }
6 i n t main ( ) {
7 i n t x =5; x 5 1000
8 i n t y =7;
9 swap(& x ,& y ) ; main
10 r e t u r n EXIT SUCCESS ;
11 }

tmp 5 968 tmp 5 968

y 996 972 y 996 972

x 1000 976 x 1000 976


y 5 996

swap(1000,996) swap(1000,996)
x 7 1000

y 7 996 y 5 996
main

x 5 1000 x 7 1000

main main

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 33 / 33
1 v o i d swap ( i n t ∗ x , i n t ∗ y ){
2 i n t tmp=∗x ;
3 ∗x=∗y ;
4 ∗y=tmp ; y 7 996
5 }
6 i n t main ( ) {
7 i n t x =5; x 5 1000
8 i n t y =7;
9 swap(& x ,& y ) ; main
10 r e t u r n EXIT SUCCESS ;
11 }

tmp 5 968 tmp 5 968

y 996 972 y 996 972

x 1000 976 x 1000 976


y 5 996

swap(1000,996) swap(1000,996)
x 7 1000

y 7 996 y 5 996
main

x 5 1000 x 7 1000

main main

Christophe Tollu (Première version des diapos par Julien David) (A209 (poste 3691) - ct@lipn.univ-paris13.fr) 24 janvier 2023 33 / 33

Vous aimerez peut-être aussi