0% ont trouvé ce document utile (0 vote)
108 vues94 pages

Chap2 Pointeurs

Le document traite des pointeurs en programmation C, expliquant leur définition, déclaration, et utilisation. Il met en avant l'importance des pointeurs pour l'accès indirect aux valeurs des variables, la gestion de la mémoire, et la création de structures de données dynamiques. Des exemples pratiques illustrent les concepts d'arithmétique des pointeurs et leur interaction avec les tableaux.

Transféré par

mohamadkawi050
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
108 vues94 pages

Chap2 Pointeurs

Le document traite des pointeurs en programmation C, expliquant leur définition, déclaration, et utilisation. Il met en avant l'importance des pointeurs pour l'accès indirect aux valeurs des variables, la gestion de la mémoire, et la création de structures de données dynamiques. Des exemples pratiques illustrent les concepts d'arithmétique des pointeurs et leur interaction avec les tableaux.

Transféré par

mohamadkawi050
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

PROGRAMMATION II

Chap2 : Les pointeurs

1
1 Variables
Les
Pointeurs

• Les variables servent à stocker les données manipulées par le programme.

Une variable en C a 4 caractéristiques :

➢ 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 ……

Attention à la distinction adresse/contenu

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)

Pour accéder à la valeur d’une variable (au


contenu de la case mémoire) Il faut
connaître son emplacement (c’est l’adresse
de la variable)

Pour connaître l’adresse d’une variable


donnée, on utilise l’opérateur &

Le nom d’une variable permet d'accéder


directement à sa valeur (adressage direct).
4
1 Pointeur : définition & déclaration
Les
Pointeurs
• Un pointeur est un objet dont le contenu est une adresse d’un autre objet.
• Le nom d'une variable est lié à la même adresse, alors qu’un pointeur peut
pointer sur différentes adresses.
• Par exemple, si on déclare une variable entière « i » initialisée à 10 et que l’on
déclare un pointeur p dans lequel on range l’adresse de « i », on a un schéma
qui ressemble à :
P i
Variable mémoire 2479546 10
Adresse 2478000 …… …… 2479546 ……

On dit que p pointe sur l’adresse mémoire occupée par la variable i

Un pointeur qui contient l'adresse de la variable, permet d'accéder


indirectement à sa valeur (adressage indirect).
5
1 Intérêts des pointeurs
Les
Pointeurs
Les pointeurs présentent de nombreux avantages :

➢ Ils sont indispensables pour permettre le passage par référence pour


les paramètres des fonctions;
➢ Allocation dynamique de la mémoire;
➢ Gestion des fichiers;
➢ Ils permettent de créer des structures de données (listes et arbres)
dont le nombre d’éléments peut évoluer dynamiquement.
➢ Ils permettent d'écrire des programmes plus compacts et efficaces.

6
1 Déclaration d’un pointeur
Les
Pointeurs

• Le type d’un pointeur dépend du type de la variable pointée. Ceci est


important pour connaître la taille de la valeur pointée.

• On déclare un pointeur par l’opération d’indirection «*» :


type *nom-du-pointeur ;

➢ type est le type de la variable pointée.


➢ * est l’opérateur qui indiquera au compilateur que c’est un pointeur.

• Remarque: la valeur d’un pointeur donne l’adresse du premier octet


parmi les n octets où la variable est stockée.

7
1 Déclaration d’un pointeur
Les
Pointeurs

Exemple :

• int *p; // déclaration d’un pointeur sur une variable entière

• float *p; // déclaration d’un pointeur sur une variable float

• char *p; // déclaration d’un pointeur sur char.

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

• int i=10, j=30; // deux variables de type int

• p=&i; // on met dans p, l’adresse de i (p pointe sur i)

• printf("*p = %d \n",*p); //affiche : *p = 10

• *p=20; // met la valeur 20 dans la case mémoire pointée par p (i vaut 20 après cette
instruction)

• p=&j; // p pointe sur j

• i=*p; // on affecte le contenu de p à i (i vaut 30 après cette instruction)


9
1 Initialisation d’un pointeur
Les
Pointeurs

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.

On peut initialiser un pointeur en lui affectant :


➢ l’adresse d’une variable
➢ un autre pointeur déjà initialisé
➢ la valeur 0 désignée par le symbole NULL, défini dans <stddef.h> (on dit
que p pointe ‘nulle part’: aucune adresse mémoire ne lui est associé)
10
1 Initialisation d’un pointeur
Les
Pointeurs
Exemples :

• Pointeur qui pointe sur une variable p i


int i=5;
int *p=&i; 2479 5
… … 2475 2479 …
• Pointeurs qui pointent sur la même adresse
int i=5; q p i
int *p=&i;
2479 2479 5
int *q=p;
… 2471 2475 2479 …
• Pointeur qui ne pointe sur rien p
int *p = NULL;
0
… … 2475 …
11
1 Opérateurs de manipulation
Les
Pointeurs

Remarque : si un pointeur P pointe sur une variable X, alors *P peut être utilisé
partout où on peut écrire X

• X+=2 équivaut à *P+=2


• ++X équivaut à ++ *P
• X++ équivaut à (*P)++ // les parenthèses ici sont obligatoires car l’associativité
des opérateurs unaires * et ++ est de droite à gauche

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

Soient P1 et P2 deux pointeurs sur le même type de données, alors l'instructions


P1 = P2; fait pointer P1 sur le même objet que P2

Remarque:
• on peut également utiliser les opérateurs ++ et -- avec les pointeurs

14
1 Opérations arithmétiques
Les
Pointeurs

Si i est un entier et p est un pointeur sur un objet de type T, l’expression


p+i désigne un pointeur sur un objet de type T dont la valeur est égale à
la valeur de p incrémentée de i*sizeof(T).
Il en va de même pour la soustraction d’un entier à un pointeur, et pour les
opérateurs d’incrémentation et de décrémentation ++ et –

#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 pointe sur b => (*P1) est équivalente à b

*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

P2 pointe sur N => (*P2) est équivalente à N

*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

PP pointe sur P2 => (*PP) est équivalente à P2

*P1 = a; b = a;

*P2 = *P2 + 1; N = N + 1;

*PP = &M; P2 = &M;

**PP = 20;

24
1 Pointeurs : Exemple
Les
Pointeurs P1 b a
PP D
G G

P2 N M
54 6
20

PP pointe sur P2 => *(*PP) est équivalente à *P2

*P1 = a; b = a;

*P2 = *P2 + 1; N = N + 1;

*PP = &M; P2 = &M;

**PP = 20; *(P2) = 20 M = 20

25
1 Pointeurs et tableaux
Les
Pointeurs

int tab[5]={1,58, 7};

• Le nom d'un tableau tab représente l'adresse de son premier élément :

(tab équivaut &tab[0])

→ on peut donc dire que tab (le nom d’un tableau) est un pointeur constant sur le
premier élément du tableau.

• En déclarant un tableau T et un pointeur P du même type, l’instruction P=T fait


pointer P sur le premier élément de T et crée une liaison entre P et le tableau T.

→ P=T; est équivalente à P=&T[0];

26
1 Pointeurs et tableaux
Les
Pointeurs

Accès à un élément t[i] :


• on part de l’adresse de début du tableau, on ajoute i et on obtient l’adresse du
ième élément.

• L’élément est obtenu par l’opérateur d’indirection *

Conséquences
➢ L’élément t[i] s’écrit aussi *(t+i)

➢ L’adresse de t[i] s’écrit &t[i] ou bien (t+i)

27
1 Pointeurs et tableaux
Les
Pointeurs

• A partir de là, on peut manipuler un tableau T en utilisant un pointeur P :


➢ P pointe sur T[0] et *P désigne T[0]
➢ P+1 pointe sur T[1] et *(P+1) désigne T[1]
➢ ….
➢ P+i pointe sur T[i] et *(P+i) désigne T[i]

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]

g) *(P+*(P+8)-A[7]) = *(P + A[8] – A[7]) = *(P + 90 - 89) = *(P + 1) = A[1] = 23


29
1 Exercice 1
Les
Pointeurs
Trouvez les erreurs dans les suites d’instruction suivantes :
➢ int *p , x = 34 ; *p = x ;

➢ int x = 17 , *p = x ; *p = 17 ;

➢ double *q ; int x = 17 , *p = &x ; q = p ;

➢ 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].

• En déclarant un tableau A[n][m] et un pointeur P du même type, on peut


manipuler le tableau A en utilisant le pointeur P en faisant pointer P sur le premier
élément de A (P=&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

➢ Tableaux de pointeurs vers des chaînes de caractères de différentes longueurs.


➢ Nous avons déclaré un tableau JOUR[] de 7 pointeurs de type char, chacun étant initialisé
avec l’adresse de l’une des 7 chaînes de caractères.

38
1 Tableau de pointeurs : exemple
Les
Pointeurs

➢ Affichage :

39
1 Exercice
Les
Pointeurs

En utilisant le formalisme pointeur, écrire un programme qui lit une matrice A de


dimensions N et M au clavier et affiche : (1) la matrice A, (2) la transposée de A.

40
1 Exercice - Correction
Les
Pointeurs

41
1 Pointeurs & Fonctions
Les
Pointeurs

1.Passage d’un pointeur à une fonction


2. Passage d’un tableau à un indice à une fonction
3. Passage d’un tableau à deux indices à une fonction

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

P pointe sur n => *P est équivalente à n


à l'aide de l'adresse contenue dans P, l'opérateur
d'indirection peut affecter une nouvelle valeur à cet
endroit de la mémoire

43
1 Pointeurs & Fonctions
Les
Pointeurs

1. Passage d’un pointeur à une fonction


2.Passage d’un tableau à un indice à une fonction
3. Passage d’un tableau à deux indices à une fonction

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

Alternative : passage d'un paramètre par élément du tableau

Solution générale : repose sur l'équivalence entre le nom du tableau et un pointeur


constant
➢ lorsqu'on transmet le nom d'un tableau, on transmet l'adresse de son
premier élément
➢ cette adresse initialise un paramètre formel de type pointeur

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

adresse du premier élément

46
Exemple : remplissage et affichage d’un tableau passé en paramètre d’une fonction

47
1 Pointeurs & Fonctions
Les
Pointeurs

Remarque : il existe une autre façon d'indiquer que la fonction reçoit un


tableau. Plutôt que d'indiquer que la fonction attend un int *tableau

void affiche(int tableau[], int tailleTableau)

Cela revient exactement au même, mais la présence des crochets permet au


programmeur de bien voir que c'est un tableau que la fonction prend, et non un
simple pointeur. Cela permet d'éviter des confusions.

48
1 Pointeurs & Fonctions
Les
Pointeurs

1. Passage d’un pointeur à une fonction


2. Passage d’un tableau à un indice à une fonction
3. Passage d’un tableau à deux indices à une fonction

49
1 Pointeurs & Fonctions
Les
Pointeurs

Même principe que pour un tableau à un seul indice : transmission


d'une adresse, mais il faut en plus indique la taille d'une ligne (c.à.d.
le nombre de colonnes)
void saisieMatrice(int (*mat)[M])
{
int i,j;
for(i=0; i<N; i++)
for(j=0; j<M; j++)
{
………
}
}

50
Exemple : remplissage et affichage d’une matrice passé en paramètre d’une fonction

51
1 Les pointeurs sur les fonctions
Les
Pointeurs

Les pointeurs sur les fonctions

objectif : arriver à appeler une fonction par son adresse.

52
1 Les pointeurs sur les fonctions
Les
Pointeurs

Rappel :

➢ Un pointeur doit avoir le même type que l’objet pointé.


Exemple : un pointeur sur int, doit contenir une adresse d'une variable int

int * pointeur; //déclare un pointeur de type int


int var; //déclare une variable de type int
pointeur = &var; //on met dans pointeur l’adresse de la variable var

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).

➢ Utilisation d’un pointeur sur un objet quelconque : pointeur générique

54
1 Les pointeurs sur les fonctions
Les
Pointeurs

Le pointeurs générique :

➢ C’est un pointeur vers un objet de n’importe quel type.

➢ Il peut contenir, soit l’adresse d’un objet de n’importe quel type, soit un autre pointeur
de n’importe quel type.

➢ Il est désigné par void *.

Exemple : void * pointeurGenerique;

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 :

➢ Si p est de type void *:


▪ on ne peut pas parler de p+i ou p-i (i étant un entier)
▪ on ne peut pas utiliser l’expression p++ (on ne connaît pas la taille des objets pointés)
▪ on ne peut pas utiliser l’opérateur d’indirection *

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

Les pointeurs et les fonctions :

➢ Une fonction a également une adresse mémoire et donc un pointeur capable de


sauvegarder cette adresse mémoire, pour qu'elle soit utilisée par la suite.

➢ Identiquement aux variables on peut utiliser l'opérateur '&', suivi du nom de la


fonction pour avoir son adresse.

59
1 Les pointeurs sur les fonctions
Les
Pointeurs

Pointeur = variable dont la valeur correspond à


de fonction à l'adresse du début
une du code d'une fonction
adresse

60
1 Les pointeurs sur les fonctions
Les
Pointeurs

Les pointeurs et les fonctions :

Exemple :

void ma_fonction(void)
{
//instructions...
}

pointeurSurFonction = &(ma_fonction); /* Cela stockera l'adresse de 'ma_fonction' dans


la variable 'pointeurSurFonction'*/

61
1 Les pointeurs sur les fonctions
Les
Pointeurs

Les pointeurs et les fonctions :

➢ Le nom d'une fonction est un pointeur dit statique. En conséquence, l'utilisation de


l'opérateur '&' est facultative, ainsi seulement par l'utilisation du nom de la fonction on
récupère son adresse.

pointeurSurFonction = ma_fonction;

62
1 Les pointeurs sur les fonctions
Les
Pointeurs

Les pointeurs et les fonctions :

➢ Si on combine les deux notions : la déclaration d’un pointeur générique, et la lecture de


l'adresse d'une fonction, on aura alors un code comme ceci :

void ma_fonction (void)


{
printf("Hello world!\n");
}

void * pointeurGenerique = ma_fonction ;


/* on a gardé l'adresse de notre fonction dans le pointeur générique. Ce pointeur ne
permet pas d’appeler la fonction/*

63
1 Les pointeurs sur les fonctions
Les
Pointeurs

➢ Généralement, un pointeur sur fonction est déclaré suivant la syntaxe :

type de retour (*nom du pointeur) (types des paramètres);

➢ Ainsi ces pointeurs sont déclarés en respectant le prototype de la fonction sur laquelle ils
vont pointer.

Exemples :

int (*ptr) (int, int, char *);

void (*ptr2) (int);


64
1 Les pointeurs sur les fonctions
Les
Pointeurs

➢ Fonction sans retour et sans arguments

➢ Fonction sans retour et avec arguments

➢ Fonction avec retour et sans arguments

➢ Fonction avec retour et avec arguments

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*/

void ma_fonction(void) /*La fonction*/


{
printf("Bonjour!\n");
}

int main(void)
{
void (*pointeurSurFonction)(void); /*Déclaration du pointeur*/

pointeurSurFonction = ma_fonction; /*Sauvegarde de l'adresse de la fonction


dans le pointeur adéquat*/

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 ma_fonction(int argint);

➢ La déclaration d'un pointeur sur ce type de fonctions est comme ceci :

void (*pointeurSurFonction)(int)

68
1 Les fonctions sans retour/avec arguments
Les
Pointeurs Fonction sans retour et avec arguments

➢ Même principe pour les fonctions à plusieurs arguments :

Exemple :

void ma_fonction(int argint,char * argchar,float leng);

void (*pointeurSurFonction)(int,char *,float);

➢ La sauvegarde de l'adresse de la fonction reste la même :

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 )

➢ La valeur de retour peut être récupérée ainsi :

variable_receptrice = (*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*/

(*pointeurSurFonction)(); /*Appel de la fonction*/

return 0;
}
Bonjour

73
1 Appels de fonctions en utilisant leurs adresses
Les
Pointeurs Exemple 2 : Fonction sans retour et avec arguments

void somme(int a, int b)


{
printf("La somme est %d\n",a+b);
}

int main (void)


{
void (*pointeurSurFonction)(int, int); /*déclaration du pointeur*/
pointeurSurFonction = afficherBonjour; /*Initialisation*/
(*pointeurSurFonction)(2,3); /*Appel de la fonction*/
return 0;
} La somme est 5

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

int sommeNombres(int a, int b)


{
return a+b;
}

int main (void)


{
int (*pointeurSurFonction)(int,int); /*déclaration du pointeur*/
int somme;
pointeurSurFonction = sommeNombres; /*Initialisation*/
somme = (*pointeurSurFonction)(5,10); /*Appel de la fonction*/
printf("La somme est : %d", somme);
return 0;
} La somme est : 15

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 :

type_de_retour (* nom_du_tableau_de_pointeurs_sur_fonctions [ taille_du_tableau ] )


( liste_des_arguments );

➢ 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

➢ Exemple pour une fonction sans arguments :

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

➢ Exemple pour une fonction avec arguments :

int fonction1(double,double)
{
return 1;
}

int (* fonction2(char str[]))(double,double)


{
printf("%s",str); /*Affichage de la chaine passée en paramètre*/
return fonction1; /*Ici le retour d'un pointeur sur fonction*/
}

80
1 Retourner un pointeur sur fonction
Les
Pointeurs Utilisation d'un typedef

➢ Avec cette méthode, on va pouvoir déclarer un pointeur sur fonction, en mettant


typedef à sa gauche :

typedef type_retour (* nom_du_pointeur) (liste_arguments)

➢ 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

➢ Exemple pour une fonction sans arguments :

typedef int (*ptrFonction)(void);

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

➢ Exemple pour une fonction avec arguments :

typedef int (*ptrFonction)(double,double);

int fonction1(double,double)
{
return 1;
}

ptrFonction fonction2(char str[])


{
printf("%s",str); /*Affichage de la chaine passée en paramètre*/
return fonction1; /*Ici le retour d'un pointeur sur fonction*/
}

83
1 Passage de pointeur de fonctions en paramètre
Les
Pointeurs

➢ Il s’agit de passer un pointeur sur fonction en paramètre à une autre fonction.

Méthode normale
void fonction1(int n)
{
printf("fonction 1 appel N° %d\n",n);
}

void fonction2(int n, void (*ptrfonction)(int))


{
(*ptrfonction)(n); /*Appel de la fonction pointée par ptrfonction*/
}
int main(void)
{
fonction2(13,fonction1);
}

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

double addition(double n1,double n2)


{
return n1 + n2;
}
double soustraction(double n1,double n2)
{
return n1 - n2;
}
double multiplication(double n1,double n2)
{
return n1 * n2;
}
double division(double n1,double n2)
{
return n1 / n2;
87
}
1 Les pointeurs sur les fonctions
Les
Pointeurs Exercice - Correction

Déclaration et initialisation d'un tableau de pointeurs sur


fonctions

double (*listeFonctions[4])(double,double) = {addition,soustraction,multiplication,division};

•Pour déclarer un pointeur sur fonction : double (*listeFonctions)(double,double)

•Donc la déclaration d'un tableau est de la forme : double (*listeFonctions[4])(double,double)

•Ce tableau est ensuite initialisé avec : {addition,soustraction,multiplication,division};

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

Ces deux algorithme sont identiques, à l'exception de l'opérateur de comparaison.


Afin d'éviter de dupliquer du code, nous allons utiliser les pointeurs de fonctions.
91
1 Les pointeurs sur les fonctions
Les
Pointeurs

➢ Ecrire une fonction superieur(int a, int b) qui renvoie 1 si a est supérieur


à b, 0 s'ils sont égaux et -1 sinon
➢ Ecrire une fonction inferieur(int a, int b) qui renvoie 1 si a est inférieur à
b, 0 s'ils sont égaux et -1 sinon
➢ Ecrire une fonction tri, qui tri un tableau t de taille n selon une fonction
compare_int
➢ Ecrire une fonction main qui teste tri

92
1 Les pointeurs sur les fonctions
Les
Pointeurs

int superieur(int a,int b) {


return (a>b)?1:((a==b)?0:-1);
}
int inferieur(int a,int b) {
return -superieur(a,b);
}

93
1 Les pointeurs sur les fonctions
Les
Pointeurs

void tri(int *t,int n,int(*compare_int)(int a ,int b)) {


int i_min,i,j,tmp;
for(i=0;i<n-1;i++){
i_min=i;
for(j=i;j<n;j++)
if((*compare_int)(t[j],t[i_min])<0)
i_min=j;
tmp=t[i_min];
t[i_min]=t[i];
t[i]=tmp;
}
}

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

Vous aimerez peut-être aussi