Vous êtes sur la page 1sur 24

Chapitre 3

LES POINTEURS

1
Plan
Introduction
Définition
Intérêts des pointeurs
Opérateurs de manipulation
Initialisation
Opérateurs arithmétiques
Pointeurs et fonctions
Allocation de la mémoire
2
Introduction

⚫ Nous avons déjà été amené à utiliser


l’opérateur & pour désigner l’adresse d’une
variable.
⚫ D’une manière générale, le langage C permet
de manipuler des adresses par l’intermédiaire
de variables nommées pointeurs.

3
Définition
⚫ Un pointeur est une variable spéciale qui
peut contenir l’adresse d’une autre variable.
Exemple : Soit A une variable contenant la
valeur 10 et P un pointeur qui contient
l'adresse de A (on dit que P pointe sur A) .

4
Définition
Remarques
• Le nom d’une variable permet d'accéder
directement à sa valeur (adressage direct).
• Un pointeur qui contient l'adresse de la
variable, permet d'accéder indirectement à sa
valeur (adressage indirect).
• Le nom d'une variable est lié à la même adresse,
alors qu’un pointeur peut pointer sur différentes
adresses.
5
Déclaration d’un pointeur

• Syntaxe: type *nom_pointeur;


- Type sur lequel il pointera
- Caractère * pour préciser que c’est un pointeur
- Nom du pointeur
• Exemple:
int *p; // p est un pointeur sur un int
char *c; // c est un pointeur sur un char

6
Intérêts des pointeurs
Les pointeurs présentent de nombreux avantages :
⚫ Ils sont indispensables pour permettre le passage
par adresse pour les paramètres des fonctions.
⚫ Ils permettent de créer des structures de
données (listes et arbres) dont le nombre d’
éléments peut évoluer dynamiquement. Ces
structures sont très utilisées en programmation.
⚫ Ils permettent d'écrire des programmes plus
compacts et efficaces.

7
Opérateurs de manipulation des pointeurs
Lors du 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.
Exemple1 :
⚫ 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 la case mémoire pointée par
p à i (i vaut 30 après cette instruction) 8
Opérateurs de manipulation des pointeurs
Exemple2 :
float a, *p;
p=&a;
printf("Entrez une valeur : \n");
scanf("%f ", p); //supposons qu’on saisit la valeur 1.5
printf("Adresse de a= %x, contenu de a= %f\n" , p,*p);
*p+=0.5;
printf ("a= %f\n" , a); //affiche a=2.0
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.
9
Initialisation d’un pointeur
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é
Remarque : Toute utilisation d’un pointeur doit être précédée
par une initialisation.

On peut initialiser un pointeur en lui affectant :


a. L’adresse d’une variable,
Ex: int a, *p1; p1=&a;
b. Un autre pointeur déjà initialisé,
Ex: int *p2; p2=p1;
c. La valeur 0 désignée par le symbole NULL.
Ex: int *p; p=NULL;
(on dit que p pointe ‘nulle part’: aucune adresse mémoire ne
lui est associé). 10
Exercice d’application
# include <stdio.h>
main()
{
int A = 1, B = 2, C = 3, *P1, *P2;
P1=&A;
P2=&C;
*P1=(*P2)++;
P1=P2;
P2=&B;
*P1-=*P2;
++*P2;
*P1*=*P2;
A=++*P2**P1;
P1=&A;
*P2=*P1/=*P2;
}
Donnez les valeurs de A, B,C,P1 et P2 après chaque instruction 11
Solution
A B C P1 P2

Init. 1 2 3 / /
P1=&A 1 2 3 &A /
P2=&C 1 2 3 &A &C
*P1=(*P2)++ 3 2 4 &A &C
P1=P2 3 2 4 &C &C
P2=&B 3 2 4 &C &B
*P1-=*P2 3 2 2 &C &B
++*P2 3 3 2 &C &B
*P1*=*P2 3 3 6 &C &B
A=++*P2**P1 24 4 6 &C &B
P1=&A 24 4 6 &A &B

*P2=*P1/=*P2 6 6 6 &A &B


12
Opérations arithmétiques avec
les pointeurs
La valeur d’un pointeur étant un entier, certaines
opérations arithmétiques sont possibles : ajouter ou
soustraire un entier à un pointeur ou faire la
différence de deux pointeurs.
Pour un entier i et des pointeurs p, p1 et p2 sur une
variable de type T :
◦ p+i (resp p-i) : désigne un pointeur sur une
variable de type T. Sa valeur est égale à celle de p
incrémentée (resp décrémentée) de i*sizeof(T).
◦ p1-p2 : Le résultat est un entier dont la valeur
est égale à(différence des adresses)/sizeof(T).
13
Opérations arithmétiques avec
les pointeurs
Remarque
1. On peut également utiliser les opérateurs ++ et --
avec les pointeurs.
2. La somme de deux pointeurs n’est pas autorisée.

Exemple :
float *p1, *p2; printf("Adresse p1 = %d \t
float z =1.5; Adresse p2 = %d\n",p1,p2);
p1=&z; printf("p2-p1 = %d \n",p2-p1);
printf("Adresse p1 = %d
\n",p1);
p1++;
p2=p1+1; 14
15
Pointeurs et fonctions
• Passage de paramètres: il y a deux méthodes pour passer
les paramètres à une fonction (passage par valeur et passage
par adresse).
• Passage par valeur: la valeur de la variable passée en
paramètre est copiée dans une variable locale. La
modification de la variable locale dans la fonction appelée
ne modifie pas la variable passée en paramètre.
• Passage par adresse: l’adresse de la variable passée en
paramètre en utilisant un pointeur. Toute modification dans
la fonction appelée entraine la modification du contenu de
la variable passée en paramètre.

16
Pointeurs et fonctions (suite)
• Exemple: passage par valeur
#include <stdio.h>
void echange (int ad1, int ad2)
{ int x ;
x = ad1 ;
ad1 = ad2 ;
ad2 = x ;
}
main() 10 20
{
int a=10, b=20 ;
printf ("avant appel %d %d\n", a, b) ;
echange (a, b) ; 10 20
printf ("après appel %d %d", a, b) ;
}

17
Pointeurs et fonctions (suite)
• Exemple: passage par adresse
#include <stdio.h>
void echange (int *ad1, int *ad2)
{ int x ;
x = *ad1 ;
*ad1 = *ad2 ;
*ad2 = x ;
}
main() 10 20
{
int a=10, b=20 ;
printf ("avant appel %d %d\n", a, b) ;
echange (&a, &b) ; 20 10
printf ("après appel %d %d", a, b) ;
}

18
Allocation de mémoire
• Principe de l’allocation dynamique: demander la
réservation d’une zone mémoire au système. Cette
demande est effectuée à l’aide des fonctions
spécialisées dont les arguments permettent de
déterminer la taille souhaitée en octets. Ces fonctions
retournent un pointeur sur la zone allouée ou un
pointeur NULL en cas d’erreur.
• Règles:
- Tester la valeur de retour de la fonction
d’allocation
- Mettre un cast pour indiquer le type (facultatif)
- Libérer la mémoire allouée à la fin du traitement
19
Allocation de mémoire (suite)

• Bibliothèques: « stdlib.h »
• Taille en octets: la fonction sizeof permet de
calculer et retourner le nombre d’octets réservés pour
un type. sizeof(type)
(Exemple: sizeof(int))
• Fonctions:
- malloc()
- calloc()
- realloc()

20
Allocation de mémoire (suite)
• malloc: allocation d’un nombre d’octets (taille:
argument de malloc) de la mémoire.
Fonction malloc(taille)
d’allocation
Nombre
d’octets

Exemple:
int *p,n=10;
p =(int*) malloc(n*sizeof(int));
if(p!=NULL)
{
………. /* traitement à faire*/
}
else
{ printf(‘’Echec de réservation \n’’); }

21
Allocation de mémoire (suite)
• calloc: allocation de mémoire pour n éléments de
longueur taille et remplissage de la zone réservée par
des zéros.
calloc(n,taille)
Fonction
Longue
d’allocation Nom ur de
bre chaque
éléme d’ élémen
nts
Exemple: t

char *c,n=5;
c =(char*) calloc(n,sizeof(char));
if(c!=NULL)
{
………. /* traitement à faire*/
}
else
{ printf(‘’Echec de réservation \n’’); }

22
Allocation de mémoire (suite)
• realloc: modification de la taille d’une zone
préalablement allouée.
realloc(k,taille)

Fonction de Nouvelle
réallocation Pointeur sur taille
l’allocation
précédente
Exemple:
int *p,n=10;
p =(int*) malloc(n*sizeof(int));

n=20;
p=(int*)realloc(p, n*sizeof(int));

23
Allocation de mémoire (suite)
• free: libération de la mémoire réservée

Fonction de free(p)
libération Pointeur sur la
zone allouée

Exemple:
int *h,n=10;
h =(int*) malloc(n*sizeof(int));

free(h);

24

Vous aimerez peut-être aussi