Chap2 Pointeurs
Chap2 Pointeurs
1
1 Variables
Les
Pointeurs
➢ un type
➢ un nom
➢ une valeur
➢ une adresse
2
1 Variables
Les
Pointeurs
• Lorsque l’on déclare une variable, par exemple un entier « i », l’ordinateur
réserve un espace mémoire pour y stocker les valeurs de i.
• L’emplacement de cet espace dans la mémoire est nommé adresse.
i
Variable mémoire 10
Adresse 2478000 …… …… 2479546 ……
3
1 Variables
Les
Pointeurs
• 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)
6
1 Déclaration d’un pointeur
Les
Pointeurs
7
1 Déclaration d’un pointeur
Les
Pointeurs
Exemple :
8
1 Opérateurs de manipulation
Les
Pointeurs
Lorsqu’on travail avec des pointeurs, nous utilisons :
➢ un opérateur 'adresse de': & pour obtenir l'adresse d'une variable
➢ un opérateur 'contenu de': * pour accéder au contenu d'une adresse
Exemple :
• int *p; //on déclare un pointeur vers une variable de type int
• *p=20; // met la valeur 20 dans la case mémoire pointée par p (i vaut 20 après cette
instruction)
A la déclaration d’un pointeur p, on ne sait pas sur quel zone mémoire il pointe. Ceci
peut générer des problèmes :
int *p;
*p = 10; //provoque un problème mémoire car le pointeur p n’a pas été initialisé
Conseil : Toute utilisation d’un pointeur doit être précédée par une initialisation.
Remarque : si un pointeur P pointe sur une variable X, alors *P peut être utilisé
partout où on peut écrire X
12
1 Arithmétique des pointeurs
Les
Pointeurs
La valeur d’un pointeur étant un entier, on peut lui appliquer un certain nombre
d’opérateurs arithmétiques classiques. Les seules opérations arithmétiques valides sur les
pointeurs sont :
▪ L’addition d’un entier à un pointeur: Le résultat est un pointeur de même type que
le pointeur de départ ;
▪ La soustraction d’un entier à un pointeur: Le résultat est un pointeur de même type
que le pointeur de départ ;
▪ La différence de deux pointeurs pointant tous deux vers des objets de même type:
Le résultat est un entier.
▪ La somme de deux pointeurs n’est pas autorisée.
13
1 Opérations arithmétiques
Les
Pointeurs
Remarque:
• on peut également utiliser les opérateurs ++ et -- avec les pointeurs
14
1 Opérations arithmétiques
Les
Pointeurs
#include <stdio.h>
main()
{
int i = 3;
p1 = 643782
int *p1, *p2;
p1 = &i; p2 = 643786
p2 = p1 + 1;
printf("p1 = %ld\t p2 = %ld\n",p1,p2);
}
15
1 Pointeurs : Exemple
Les
Pointeurs Compilation
Programme exécutable
Mémoire
Code source adresse
10
char a = 'G', b='D'; 11
12
char *P1 = &b; 13
14
int N = 4, M = 6; 15
16
17
int *P2 = &N; 18
19
int **PP = &P2; 20
21
22
23
24
25
26 16
27
1 Pointeurs : Exemple
Les Mémoire
adresse
Pointeurs 10 G a
11 D b
12
char a = 'G', b='D';
13
14
char *P1 = &b; 15
16
int N = 4, M = 6; 17
18
int *P2 = &N; 19
20
21
int **PP = &P2;
22
23
24
25
26
27
28
29
30 17
31
1 Pointeurs : Exemple
Les Mémoire
adresse
Pointeurs 10 G a
11 D b
12
char a = 'G', b='D';
13 P1
14
11
char *P1 = &b; 15
16 Le lien de P1 vers b
int N = 4, M = 6; 17
suffit pour comprendre
18
19
le fonctionnement du
int *P2 = &N;
20 programme.
21 La connaissance de
int **PP = &P2;
22 l'adresse dans P1 n'est
23 pas nécessaire
24
25
26
27
28
29
30 18
31
1 Pointeurs : Exemple
Les Mémoire
adresse
Pointeurs 10 G a
11 D b
12
char a = 'G', b='D';
13 P1
14
11
char *P1 = &b; 15
16
int N = 4, M = 6; 17
18
4 N
int *P2 = &N; 19
20
21
int **PP = &P2; 6 M
22
23
24
25
26
27
28
29
30 19
31
1 Pointeurs : Exemple
Les Mémoire
adresse
Pointeurs 10 G a
11 D b
12
char a = 'G', b='D';
13 P1
14
11
char *P1 = &b; 15
16
int N = 4, M = 6; 17
18
4 N
int *P2 = &N; 19
20
21
int **PP = &P2; 6 M
22
23
24
25
26
16 P2
27
28
29
30 20
31
1 Pointeurs : Exemple
Les Mémoire
adresse
Pointeurs 10 G a
11 D b
12
char a = 'G', b='D';
13 P1
14
11
char *P1 = &b; 15
16
int N = 4, M = 6; 17
18
4 N
int *P2 = &N; 19
20
21
int **PP = &P2; 6 M
22
23
24
25
26
16 P2
27
28
29 PP
30
24
21
31
1 Pointeurs : Exemple
Les
Pointeurs P1 b a
PP D
G G
P2 N M
4 6
*P1 = a; b = a;
*P2 = *P2 + 1;
*PP = &M;
**PP = 20;
22
1 Pointeurs : Exemple
Les
Pointeurs P1 b a
PP D
G G
P2 N M
54 6
*P1 = a; b = a;
*P2 = *P2 + 1; N = N + 1;
*PP = &M;
**PP = 20;
23
1 Pointeurs : Exemple
Les
Pointeurs P1 b a
PP D
G G
P2 N M
54 6
*P1 = a; b = a;
*P2 = *P2 + 1; N = N + 1;
**PP = 20;
24
1 Pointeurs : Exemple
Les
Pointeurs P1 b a
PP D
G G
P2 N M
54 6
20
*P1 = a; b = a;
*P2 = *P2 + 1; N = N + 1;
25
1 Pointeurs et tableaux
Les
Pointeurs
→ on peut donc dire que tab (le nom d’un tableau) est un pointeur constant sur le
premier élément du tableau.
26
1 Pointeurs et tableaux
Les
Pointeurs
Conséquences
➢ L’élément t[i] s’écrit aussi *(t+i)
27
1 Pointeurs et tableaux
Les
Pointeurs
Exemple:
int x, A[7]={5,0,9,2,1,3,8};
int *P;
P=A;
x=*(P+5); x est égale à la valeur de A[5]
28
1 Exercice 1
Les
Soit P un pointeur qui pointe sur un tableau A tel que :
Pointeurs int A[] = {12, 23, 34, 45, 56, 67, 78, 89, 90};
int *P;
P = A;
Quelles valeurs ou adresses fournissent ces expressions:
a) *P+2 = 14
b) *(P+2) =34
c) &A[4]-3 =&A[1]
d) A+3 =&A[3]
e) &A[7]-P = P + 7 – P = 7
f) P+(*P-10) =&A[2]
➢ int x = 17 , *p = x ; *p = 17 ;
➢ int x, *p ; &x = p ;
30
1 Exercice 1
Les
Pointeurs
Trouvez les erreurs dans les suites d’instruction suivantes :
➢ int *p , x = 34 ; *p = x ;
➢ *p = x est incorrect parce que le pointeur p n’est pas initialisé
➢ int x = 17 , *p = x ; *p = 17 ;
➢ *p = x est incorrect. Pour que p pointe sur x on doit avoir p = &x
➢ double *q ; int x = 17 , *p = &x ; q = p ;
➢ q = p incorrect. q et p deux pointeurs sur des types différent
➢ int x, *p ; &x = p ;
➢ &x = p incorrect. &x n’est pas une variable (lvalue) et par
conséquent ne peut pas figurer à gauche d’une affectation
31
1 Pointeurs : saisie et affichage d’un tableau
Les
Pointeurs Version 1 :
main()
{
float T[100] , *P;
int i,n;
do {printf("Entrez n \n " );
scanf(" %d" ,&n);
}while(n<0 ||n>100);
P=T;
for(i=0;i<n;i++)
{ printf ("Entrez T[%d] \n ",i );
scanf(" %f" , P+i );
}
for(i=0;i<n;i++)
printf (" %f \t",*(P+i));
}
32
1 Pointeurs : saisie et affichage d’un tableau
Les
Pointeurs Version 2 :
main()
{
float T[100] , *P;
int n;
do {printf("Entrez n \n " );
scanf(" %d" ,&n);
}while(n<0 ||n>100);
for(P=T;P<T+n;P++)
{ printf ("Entrez T[%d] \n ",P-T );
scanf(" %f" , P);
}
for(P=T;P<T+n;P++)
printf (" %f \t",*P);
}
33
Pointeurs et tableaux à deux
1 dimensions
Les
Pointeurs
• Le nom d'un tableau A à deux dimensions est un pointeur constant sur le premier
élément du tableau càd A[0][0].
34
Pointeurs et tableaux à deux
1 dimensions
Les
Pointeurs
Ainsi :
▪ P pointe sur A[0][0] et *P désigne A[0][0]
▪ P+1 pointe sur A[0][1] et *(P+1) désigne A[0][1]
▪ ….
▪ P+M pointe sur A[1][0] et *(P+M) désigne A[1][0]
▪ ….
▪ P+i*M pointe sur A[ i][0] et *(P+i*M) désigne A[i][0]
▪ ….
▪ P+i*M+j pointe sur A[ i][ j] et *(P+i*M+j) désigne A[i][j]
35
Pointeurs : saisie et affichage d’une
1 matrice
Les
Pointeurs
#define N 10
#define M 20
main( )
{ int i, j, A[N][M], *P;
P=&A[0][0];
for(i=0;i<N;i++)
for(j=0;j<M;j++)
{
printf ("Entrez A[%d][%d]\n ",i,j );
scanf(" %d" , P+i*M+j );
}
for(i=0;i<N;i++)
{ for(j=0;j<M;j++)
printf (" %d \t",*(P+i*M+j));
printf ("\n");
}
}
36
1 Pointeurs et tableaux : remarques
Les
Pointeurs
En C, on peut définir :
➢ Un tableau de pointeurs :
Ex : int *T[10]; //déclaration d’un tableau de 10 pointeurs d’entiers
➢ Un pointeur de tableaux :
Ex : int (*P)[20]; //déclaration d’un pointeur sur des tableaux de 20 éléments
➢ Un pointeur de pointeurs :
Ex : int **P; //déclaration d’un pointeur qui pointe sur des pointeurs d’entiers
37
1 Tableau de pointeurs : exemple
Les
Pointeurs
38
1 Tableau de pointeurs : exemple
Les
Pointeurs
➢ Affichage :
39
1 Exercice
Les
Pointeurs
40
1 Exercice - Correction
Les
Pointeurs
41
1 Pointeurs & Fonctions
Les
Pointeurs
42
1 Pointeurs & Fonctions
Les
Pointeurs
1. Appel de la fonction f
n
3
10
adresse de n
2. Appel de la fonction h
P
43
1 Pointeurs & Fonctions
Les
Pointeurs
44
1 Pointeurs & Fonctions
Les
Pointeurs
On ne peut pas passer un tableau complet à une fonction qui travaillerait sur une
copie locale de ce tableau dans la fonction
Conséquence : un tableau passé à une fonction est modifiable dans cette fonction
45
1 Pointeurs & Fonctions
Les
Pointeurs
Exemple : tab 11
10
12
20
13
30
P
46
Exemple : remplissage et affichage d’un tableau passé en paramètre d’une fonction
47
1 Pointeurs & Fonctions
Les
Pointeurs
48
1 Pointeurs & Fonctions
Les
Pointeurs
49
1 Pointeurs & Fonctions
Les
Pointeurs
50
Exemple : remplissage et affichage d’une matrice passé en paramètre d’une fonction
51
1 Les pointeurs sur les fonctions
Les
Pointeurs
52
1 Les pointeurs sur les fonctions
Les
Pointeurs
Rappel :
53
1 Les pointeurs sur les fonctions
Les
Pointeurs
Ce typage des pointeurs peut s’avérer gênant dans certaines circonstances telles
que celles où une fonction doit manipuler les adresses d’objets de type non connu
(ou, plutôt susceptible de varier d’un appel à un autre).
54
1 Les pointeurs sur les fonctions
Les
Pointeurs
Le pointeurs générique :
➢ Il peut contenir, soit l’adresse d’un objet de n’importe quel type, soit un autre pointeur
de n’importe quel type.
55
1 Les pointeurs sur les fonctions
Les
Pointeurs
Le pointeurs générique :
C’est un pointeur sans type → on ne peut pas utiliser des opérations arithmétiques :
56
1 Les pointeurs sur les fonctions
Les
Pointeurs
Le pointeurs générique :
➢ Un objet pointé par un pointeur générique ne peut contenir une valeur qu’après avoir
spécifié le type de l’objet pointé par le pointeur générique par le type de la valeur.
➢Un pointeur ne peut contenir un pointeur générique qu’après avoir spécifié le type du
pointeur générique par le type du pointeur.
57
1 Les pointeurs sur les fonctions
Les Le pointeurs générique :
Pointeurs
Exemple :
INT I ;
FLOAT F ;
VOID *P ;
INT *Q ;
P = &I ; // permit
P = &F ; // permit
*P = 2.5 ; // interdit
*(FLOAT *)P = 2.5 ; // permit
P=Q; // permit
Q=P; // interdit
Q = (INT *)P ; // permit
58
1 Les pointeurs sur les fonctions
Les
Pointeurs
59
1 Les pointeurs sur les fonctions
Les
Pointeurs
60
1 Les pointeurs sur les fonctions
Les
Pointeurs
Exemple :
void ma_fonction(void)
{
//instructions...
}
61
1 Les pointeurs sur les fonctions
Les
Pointeurs
pointeurSurFonction = ma_fonction;
62
1 Les pointeurs sur les fonctions
Les
Pointeurs
63
1 Les pointeurs sur les fonctions
Les
Pointeurs
➢ Ainsi ces pointeurs sont déclarés en respectant le prototype de la fonction sur laquelle ils
vont pointer.
Exemples :
65
1 Les fonctions sans retour/sans arguments
Les
Pointeurs Fonction sans retour et sans arguments
➢ On appelle procédure ou fonction sans retour, toutes fonctions ayant le type void comme
type de retour : void ma_fonction(....);
➢ On appelle fonction sans arguments (ou sans paramètres), toutes fonctions ayant le type
void en argument : void ma_fonction(void);
➢ Ainsi la déclaration d'un pointeur sur ce type de fonctions, à savoir sans arguments et sans
retour, est comme ceci :
void (*pointeurSurFonction)(void);
66
1 Les fonctions sans retour/sans arguments
Les
Pointeurs Fonction sans retour et sans arguments
Exemple :
void ma_fonction(void); /*Prototype*/
int main(void)
{
void (*pointeurSurFonction)(void); /*Déclaration du pointeur*/
return 0;
}
67
1 Les fonctions sans retour/avec arguments
Les
Pointeurs Fonction sans retour et avec arguments
➢ Une fonction est dite avec argument si dans la liste de ses arguments, il y en a, au moins
un, différent du type void :
void (*pointeurSurFonction)(int)
68
1 Les fonctions sans retour/avec arguments
Les
Pointeurs Fonction sans retour et avec arguments
Exemple :
pointeurSurFonction = ma_fonction;
69
1 Les fonctions avec retour/sans arguments
Les
Pointeurs Fonction avec retour
➢ Une fonction est dite "avec retour" quand le type de retour est différent du void.
Sans arguments
La déclaration d'un pointeur sur une fonction du genre int ma_fonction(void) est :
int (*pointeurSurFonction)(void)
Avec arguments
La déclaration d'un pointeur sur une fonction du genre int * ma_fonction(double * f,int n) est :
int * (*pointeurSurFonction)(double*,int);
70
1 Appels de fonctions en utilisant leurs adresses
Les
Pointeurs Opérateur d'appel de fonctions
➢ L'appel aux fonctions est caractérisé par la présence de parenthèses '()'. Dans le cas
général, on appellera une fonction à partir de son pointeur ainsi :
(*nom_du_pointeur_sur_fonction)( liste_d'arguments )
72
1 Appels de fonctions en utilisant leurs adresses
Les
Pointeurs Exemple 1 : Fonction sans retour et sans arguments
void afficherBonjour(void)
{
printf("Bonjour\n");
}
int main (void)
{
void (*pointeurSurFonction)(void); /*déclaration du pointeur*/
pointeurSurFonction = afficherBonjour; /*Initialisation*/
return 0;
}
Bonjour
73
1 Appels de fonctions en utilisant leurs adresses
Les
Pointeurs Exemple 2 : Fonction sans retour et avec arguments
74
1 Appels de fonctions en utilisant leurs adresses
Les
Pointeurs Exemple 3 : Fonction avec retour et sans arguments
int saisirNombre(void)
{
int n;
printf("Saisissez un nombre entier : ");
scanf("%d",&n);
return n; Saisissez un nombre entier : 4
} Le nombre est : 4
int main (void)
{
int (*pointeurSurFonction)(void); /*déclaration du pointeur*/
int nombre;
pointeurSurFonction = saisirNombre; /*Initialisation*/
nombre = (*pointeurSurFonction)(); /*Appel de la fonction*/
printf("Le nombre est : %d",nombre);
return 0;
}
75
1 Appels de fonctions en utilisant leurs adresses
Les
Pointeurs Exemple 4 : Fonction avec retour et avec arguments
76
1 Tableau de pointeurs sur fonctions
Les
Pointeurs
➢ La déclaration d'un tableau de pointeurs sur fonction se fait sous la forme suivante :
➢ Son utilisation est soumise à toutes les règles d'utilisation des tableaux ordinaires, à
savoir le premier indice est 0 et le dernier est taille – 1
➢ Tous les pointeurs qui seront stockés dedans doivent avoir le même type (les fonctions
qu'on mettra dedans doivent avoir le même prototype, càd le même type de retour et
les mêmes arguments).
77
1 Retourner un pointeur sur fonction
Les
Pointeurs Méthode normale
➢ Si l'on souhaite retourner un pointeur sur fonctions dans une de nos fonctions, on
utilise la syntaxe suivante :
type_de_retour_de_la_fonction_pointee (* nom_de_la_fonction_de_renvoi
(liste_arguments))(liste_arguments_fonction_pointee)
78
1 Retourner un pointeur sur fonction
Les
Pointeurs Méthode normale
int fonction1(void)
{
return 1;
}
int (* fonction2(void))(void)
{
return fonction1; /*Ici le retour d'un pointeur sur fonction*/
}
79
1 Retourner un pointeur sur fonction
Les
Pointeurs Méthode normale
int fonction1(double,double)
{
return 1;
}
80
1 Retourner un pointeur sur fonction
Les
Pointeurs Utilisation d'un typedef
➢ Et ceci dans le champ des déclarations globales (c'est-à-dire en dehors des fonctions).
81
1 Retourner un pointeur sur fonction
Les
Pointeurs Utilisation d'un typedef
int fonction1(void)
{
return 1;
}
ptrFonction fonction2(void)
{
return fonction1; /*Ici le retour d'un pointeur sur fonction*/
}
82
1 Retourner un pointeur sur fonction
Les
Pointeurs Utilisation d'un typedef
int fonction1(double,double)
{
return 1;
}
83
1 Passage de pointeur de fonctions en paramètre
Les
Pointeurs
Méthode normale
void fonction1(int n)
{
printf("fonction 1 appel N° %d\n",n);
}
84
1 Passage de pointeur de fonctions en paramètre
Les
Pointeurs
Utilisation de typedef
➢ Permet d'utiliser le pointeur de fonction comme n'importe quel autre type
typedef void (*ptrfonction)(int);
void fonction1(int n)
{
printf("fonction 1 appel N° %d\n",n);
}
void fonction2(int n, ptrfonction ptr)
{
(*ptr)(n); /*Appel de la fonction pointée par ptrfonction*/
}
int main(void)
{
fonction2(13,fonction1);
}
85
1 Les pointeurs sur les fonctions
Les
Pointeurs Exercice
Ecrire un programme qui affiche un menu avec les calculs d'addition, soustraction,
multiplication et division à l'utilisateur, et lui demande d'en choisir un. Ensuite il lui
demande de saisir les opérandes.
Le programme devra faire le calcul choisi avec les opérandes entrées, et afficher le résultat.
Etapes :
1)Les fonctions de calcul : écrire 4 fonctions traitants les différents calculs (addition,
soustraction, multiplication et division)
2)Déclaration et initialisation d'un tableau de pointeurs sur fonctions : créer un tableau
de pointeurs sur fonctions, qu'on initialisera avec les fonctions de calcul
3)Affichage du menu : créer une fonction qui va afficher un menu, proposant à l'utilisateur
de choisir une opération
4)La fonction main : appel de la fonction, lecture des opérandes et affichage du résultat
86
1 Les pointeurs sur les fonctions
Les
Pointeurs Exercice - Correction
Les fonctions de calcul
88
1 Les pointeurs sur les fonctions
Les
Pointeurs Exercice - Correction
Affichage du menu
89
1 Les pointeurs sur les fonctions
Les
Pointeurs Exercice - Correction
La fonction main
90
1 Les pointeurs sur les fonctions
Les
Pointeurs
92
1 Les pointeurs sur les fonctions
Les
Pointeurs
93
1 Les pointeurs sur les fonctions
Les
Pointeurs
94
1 Les pointeurs sur les fonctions
Les
Pointeurs
int main() {
int tab[ ] = { 6 , 2 , 8 , 6 , 4 , 8 , 2 , 9 , 2 , 1 };
int taille=sizeof(tab)/sizeof(int);
tri(tab , taille , &superieur);
afficher_tableau(tab , taille);
tri(tab , taille , &inferieur);
afficher_tableau(tab , taille);
}
95