Vous êtes sur la page 1sur 7

L1 Informatique Universit Paris 8 - 2010-2011

Programmation Imprative I
Rim Chaabane rchaabane@ai.univ-paris8.fr

- Cours 6 -

Les pointeurs
Le langage C permet de manipuler des adresses dobjets ou de fonctions par le biais de
pointeurs. Pour ce faire on peut dsigner des variables dites de type pointeur, destines
contenir des adresses mmoires.
Les pointeurs sont fortement typs, par exemple nous ne pouvons pas placer des caractres dans
ladresse mmoire pointe par un pointeur de type entier. Lutilisation de loprateur cast peut
toutefois autoriser certaines conversions.
Il nous est possible effectuer, dans une certaine mesure, des oprations arithmtiques sur les
pointeurs : incrmentation, dcrmentation, soustraction. Ces oprations vont plus loin quun
simple calcul dadresse, elles prennent en compte la taille des objets points.
Nous verrons galement quil y a une troite relation entre la notion de tableau et celle de
pointeur.

1. La notion de pointeur
La dclaration suivante :
int *adr ;
Prcise que adr est une variable de type pointeur sur des objets de type int.

1.1. Attribuer une valeur une variable de type pointeur


Etant donn que la variable adr na pas encore t initialises, alors sa valeur est pour linstant
indfinie. Pour attribuer une valeur adr, il faut la faire pointer sur un entier prcis. Pour faire
cela il existe diffrentes mthodes :
Mthode 1 :
int n ;
adr = &n ;
ou
int tab[3] ;
adr = &tab[0] ;

L1 Informatique Universit Paris 8 - 2010-2011


Programmation Imprative I
Rim Chaabane rchaabane@ai.univ-paris8.fr

- Cours 6 -

Mthode 3 :
#include <stdlib.h>
Adr = (int) malloc( sizeof(int) );
La premire mthode consiste affecter adr ladresse rserve la variable n ou llment
dindice 0 du tableau dentiers tab[0].
La seconde mthode consiste allouer dynamiquement un emplacement mmoire dune taille
gale au type qui y sera stock.

1.2.

Loprateur *

Cet oprateur sert accder la valeur de lobjet point. Si adr est un pointeur alors *adr est
lobjet point par adr. Exemple :
int * adr;
int n = 20;
ad = &n; /*ad pointe sur l'entier n
qui contient la valeur 20 */
printf("%d", *ad); /*affiche la valeur de 20 */
*ad = 30;
printf("%d", *ad); /*affiche la valeur de 30 */
printf("%d", n); /* affiche la valeur de 30 aussi */

Lavant dernire instruction est quivalente :


n = 30;

Lintrt dune telle utilisation peut savrer utile, comme dans le cas suivant :
...
if (n>p)
adr = &n;
else
adr = &p;
...
*adr = 30; /* place la valeur de 30 dans n ou dans p suivant le cas */

Si lemplacement adr avait t allou dynamiquement alors lon pourrait affecter une valeur
ladresse mmoire rserve de la mme faon :
adr = malloc(sizeof(int)) ;
*adr = 30;

1.3.

Exemples de dclarations de pointeurs

Dclaration de pointeurs sur des objets de type de base ou de type structure, ou dfini par
typedef.

L1 Informatique Universit Paris 8 - 2010-2011


Programmation Imprative I
Rim Chaabane rchaabane@ai.univ-paris8.fr

- Cours 6 -

unsigned int n, *ptr, q,


*adr;

adr et ptr sont des pointeurs sur des lments


de type unsigned int
Il est ncssaire de rpter le symbole * dans
chaque dclarateur de pointeur.
ps est un pointeur sur des structures de type
struct point.
s est une structure de type struct point.

vecteur est synonyme de int[3]


pv est un pointeur sur des tableaux de 3 int

struct point {
char nom;
int x, y;
};
struct point *ps, s;
typedef int vecteur[3];
vecteur *pv;
pointeur de pointeur
float x, *pf, **ppf;

int (**chose)[10];

int *pt[10];

int **ppt[10];

int *f(float x);

x est un float et pf est un pointeur sur un float


**ppf est un float
*ppf est un pointeur sur un float
ppf est un pointeur sur un pointeur sur un float
(* *chose)[10] est un int
(* *chose) est un tableau de 10 int
*chose est un pointeur sur un tableau de 10 int
chose est un pointeur de pointeur sur un
tableau de 10 int
Attention bien mettre les parenthses ici. Sans les
parenthses linterprtation est diffrente comme nous
pouvons le voir dans la suite.
- *pt[10] est un int
- pt[10] est un pointeur sur un int
- pt est un tableau de 10 pointeurs sur un int
- **ppt[10] est un int
- *ppt[10] est un pointeur sur un int
- ppt[10] est un pointeur sur un pointeur sur un
int
- ppt est un tableau de 10 pointeurs sur un
pointeur sur un int
- *f(float x) est un int
- f(float x) est un pointeur sur un int
- f est une fonction recevant un float et
retournant un pointeur sur un int

2. Les proprits des pointeurs


2.1.

Oprations entre pointeurs

Addition ou soustraction dun entier un pointeur :

Si nous dclarons un pointeur comme ci-dessous :


int * adr;

L1 Informatique Universit Paris 8 - 2010-2011


Programmation Imprative I
Rim Chaabane rchaabane@ai.univ-paris8.fr

- Cours 6 -

alors lexpression adr + 1 va retourner un pointeur sur un int et sa valeur est ladresse de lentier
suivant lentier point par adr.

On pourra relever que la diffrence entre ladresse de pn et pn+1 est de 4. Cette valeur
correspond au nombre doctets dun int.
pn + 1 ne modifie pas le contenu de pn. Par contre lappel pn++ va faire pointer pn vers
ladresse (pn+1) et dans ce cas le contenu de pn vas changer.
De la mme faon :
pn+3
permet de pointer sur un int qui se troive trois adresses plus loin que celle contenue dans pn.
Donc attention lemploi de cette opration !! /!\ pn++ != (pn+1)

Soustraction entre deux pointeurs :

Il est possible de soustraire les valeurs de deux pointeurs de mme type. Comme nous lavons vu
prcdemment, en additionnant un entier n un pointeur pn cela nous positionne sur la nime
adresse devant pn. Soit par exemple les pointeurs suivants :
int *pn, *pm;
pm = pn + 4;
printf("%d", pn - pm); /* va afficher 4 */

pm pn va retourner 4 qui correspond au nombres dadresses mmoires contenant un int entre


pm et pn.
De mme dans le cas suivant :
int t[10];
int *pn = &t[3];
int *pm = &t[8];
pm - pn /* va retourner 5 */

Il y a bien 5 lments de type int sparant t[3] et t[8].


4

L1 Informatique Universit Paris 8 - 2010-2011


Programmation Imprative I
Rim Chaabane rchaabane@ai.univ-paris8.fr

2.2.

- Cours 6 -

Lien entre pointeurs et tableaux

Tableau une dimension :

Soit un tableau tab de int et un pointeur pn sur un int dclars comme suit :
int tab[10], *pn;

Pour accder au nime lment du tableau, on fait appel tab[n].


Maintenant faisons pointer pn sur le premier lment du tableau tab :
pn = &tab[0]; /* ou pn = &tab; ce qui est quivalent */

Pour accder au nime lment du tableau, il suffit dcrire :


tab[n] ou *(pn + n)
Exemple :
int *pn, tab[5]={4,2,7,0,6};
printf("%d\n", tab[3]); /* affiche 0 */
pn = &tab;
printf("%d\n", *(pn+3)); /* affiche 0 aussi */

Ainsi, dclarer un tableau revient dclarer un pointeur sur un int. Comme nous venons de voir
pour accder au nime lment du tableau :
- soit nous faisons appel au pointeur pn : *(pn+3)
- soit nous utilisons les indices du tableau : tab[n]
- soit nous utilisons directement le tableau comme un pointeur : *(tab+3)
Donc t[i] est quivalent *(t+i).
De mme *(pn+i) quivaut pn[i] mme si pn est de type pointeur il nous est possible daccder
au i me lment de mme type avec lemploi des indices, tout comme pour les tableaux.

Tableau deux dimensions :

Lexpression t[i][j] sinterprte comme (t[i])[j], ce qui peut se traduire par :


T[j] <-> *(T+j) <-> *( *(t+i) +j)
Pour rsumer, nous avons :
&t[0] <-> t
&t[i] <-> t+i
t[1] <-> *(t+1)
t[i] <-> *(t+i)
t[i][0] <-> *t[i] <-> **(t+i)
t[i][j] <-> (t[i])[j] <-> ( *(t+i))[j] <-> *( *(t+i) + j)

L1 Informatique Universit Paris 8 - 2010-2011


Programmation Imprative I
Rim Chaabane rchaabane@ai.univ-paris8.fr

- Cours 6 -

3. Le pointeur NULL et le pointeur gnrique void *


Le pointeur NULL :
Le symbole NULL du langage C permet dinitialiser un pointeur qui ne pointe sur rien. Cette
valeur NULL peut tre affecte tout pointeur quel que soit sont type.
Ce symbole est dfini dans les librairies stdio.h, stdlib.h.
int *pn = NULL ;

En utilisant le pointeur NULL, cela nous permet alors de comparer si deux pointeurs sont gaux
(oprateur ==) ou non gaux ( !=) entre eux. Par contre les comparaisons dingalit (<,>,>=,
>=) ne sont pas autoriss avec les pointeurs sauf si lon manipule des tableaux.
Ds que lon dclare une variable de type pointeur, il est prfrable de linitialiser NULL,
surtout dans le cas ou lon ne connait pas sa valeur initiale au dbut du programme.
Au moment dutiliser un pointeur, il est prfrable de tester si sa valeur est bien non nulle :
if(pn != NULL)
*pn = ...

Equivalent :
if(pn)
*pn = ...

Cela savrera utile pour la gestion des listes chanes.

Le pointeur gnrique :

Nous avons vu jusqu maintenant quun pointeur pointe sur un objet typ. Or il est possible de
dclarer un pointeur sans type. Comme pour les dclarations de fonction, il nous est possible de
dclarer des fonctions sans type. Particulirement lorsquelles ne renvoient aucun rsultat.
Il nous est donc aussi possible de dclarer des pointeurs sans type particulier. Dans ce cas ce sera
ladresse contenu dans le pointeur qui aura un sens.
Ceci est particulirement utile lorsque :
- Une fonction doit traiter des objets de diffrents types, alors quelle a reu ladresse de
lobjet en argument.
- Lon souhaite seulement changer les valeurs de deux pointeurs.
Un pointeur de type gnrique se dclare comme suit : void * pn;
void *pn, *pm, n;
pn++;
pn = pn + 5;
int i = pm - pn;
int *pi;
if (pn != pi)
if (pn == pi)

/*
/*
/*
/*

incorrect, n ne peut tre de type void*/


interdit */
l'expression p + 5 est interdite */
l'expression pm -pn est interdite */

/* correct */
/* correct */

L1 Informatique Universit Paris 8 - 2010-2011


Programmation Imprative I
Rim Chaabane rchaabane@ai.univ-paris8.fr

- Cours 6 -

4. Le cast dun pointeur


Exemple :
char * pc ;
int * pi ;
pi= (int *) pc ;
ou
pc = (char *) pi ;