École Supérieure de Technologie
et d’Informatique
A.U. 2011/2012
Cours programmation en langage C
Chapitre 6 : Les pointeurs (9 pages)
Informatique Appliquée 1ère année
1. Adressage direct
Dans la programmation, nous utilisons des variables pour stocker des informations. La
valeur d'une variable se trouve à un endroit spécifique dans la mémoire interne de
l'ordinateur. Le nom de la variable nous permet alors d'accéder directement à cette valeur.
Adressage direct: Accès au contenu d'une variable par le nom de la variable.
int a=10 ;
printf(« %d »,a) ; // affichage : 10
printf(« %p »,&a) ; // affichage : F800
a
10
F800
2. Adressage indirect
Si nous ne voulons ou ne pouvons pas utiliser le nom d'une variable a, nous pouvons copier
l'adresse de cette variable dans une variable spéciale p, appelée pointeur. Ensuite, nous
pouvons retrouver l'information de la variable a en passant par le pointeur p.
Adressage indirect: Accès au contenu d'une variable, en passant par un pointeur qui
contient l'adresse de la variable.
Exemple
Soit a une variable contenant la valeur 10 et q un pointeur qui contient l'adresse de a. En
mémoire, a et q peuvent se présenter comme suit:
int a=10 ;
int *q ;
q=&a ;
q
q pointe sur a
F802H
F400H
printf(« %d »,a) ; => 10
printf(« %p », &a) ; => F802H
printf(« %p », q) ; => F802H
printf(« %p », &q) ; => F400H
printf(« %d », *q) ; => 10
lorsque q pointe sur a, alors (*q ) (cid:1) a
a
10
F802H
Mme Wiem Yaiche Elleuch
les pointeurs
Page 1
Définition: Pointeur
Un pointeur est une variable spéciale qui contient l'adresse d'une autre variable.
En C, chaque pointeur est limité à un type de données. Il peut contenir l'adresse d'une
variable simple de ce type ou l'adresse d'une composante d'un tableau de ce type.
Si un pointeur q contient l'adresse d'une variable a, on dit que 'q pointe sur a'.
Remarque
Les pointeurs et les noms de variables ont le même rôle: Ils donnent accès à un
emplacement dans la mémoire interne de l'ordinateur. Il faut quand même bien faire la
différence:
- Un pointeur est une variable qui peut 'pointer' sur différentes adresses.
- Le nom d'une variable reste toujours lié à la même adresse.
3. Les opérateurs de base
Lors du travail avec des pointeurs, nous avons besoin
- d'un opérateur 'adresse de' : & pour obtenir l'adresse d'une variable.
- d'un opérateur 'contenu de': * pour accéder au contenu d'une adresse.
- d'une syntaxe de déclaration pour pouvoir déclarer un pointeur.
L'opérateur 'adresse de' : &
&<NomVariable> fournit l'adresse de la variable <NomVariable>
L'opérateur & nous est déjà familier par la fonction scanf, qui a besoin de l'adresse de ses
arguments pour pouvoir leur attribuer de nouvelles valeurs.
Exemple
int n;
printf("donner un nombre entier : ");
scanf("%d", &n);
Attention !
L'opérateur & peut seulement être appliqué à des objets qui se trouvent dans la mémoire
interne, c.-à-d. à des variables et des tableaux. Il ne peut pas être appliqué à des constantes
ou des expressions.
L'opérateur 'contenu de' : *
*<NomPointeur> désigne le contenu de l'adresse référencée par le pointeur <NomPointeur>
Déclaration d'un pointeur
<Type> *<NomPointeur> ; déclare un pointeur <NomPointeur> qui peut recevoir des
adresses de variables du type <Type>
Remarque
Lors de la déclaration d'un pointeur en C, ce pointeur est lié explicitement à un type de
données. Ainsi, la variable q déclarée comme pointeur sur int ne peut pas recevoir l'adresse
d'une variable d'un autre type que int.
4. Les opérations élémentaires sur pointeurs
En travaillant avec des pointeurs, nous devons observer les règles suivantes:
Priorité de * et &
Mme Wiem Yaiche Elleuch
les pointeurs
Page 2
• Les opérateurs * et & ont la même priorité que les autres opérateurs unaires (la
négation !, l'incrémentation ++, la décrémentation --). Dans une même expression,
les opérateurs unaires *, &, !, ++, -- sont évalués de droite à gauche.
• Si un pointeur P pointe sur une variable X, alors *P peut être utilisé partout où on
peut écrire X.
Exemple
Après l'instruction P = &X;
Publicité
les expressions suivantes, sont équivalentes:
Y = *P+1
Y = X+1
P = P+10
X = X+10
*P += 2
X += 2
++*P
++X
(*P)++
X++
Dans le dernier cas, les parenthèses sont nécessaires:
On peut uniquement affecter des adresses à un pointeur.
Les pointeurs sont aussi des variables et peuvent être utilisés comme telles. Soit P1 et P2
deux pointeurs sur int, alors l'affectation
P1 = P2;
copie le contenu de P2 vers P1. P1 pointe alors sur le même objet que P2.
5. Pointeurs et tableaux
En C, il existe une relation très étroite entre tableaux et pointeurs. Ainsi, chaque opération
avec des indices de tableaux peut aussi être exprimée à l'aide de pointeurs. En général, les
versions formulées avec des pointeurs sont plus compactes et plus efficientes.
Adressage des composantes d'un tableau
Le nom d'un tableau représente l'adresse de son premier élément. En d'autre termes:
&tableau[0] et tableau sont une seule et même adresse.
En simplifiant, nous pouvons retenir que le nom d'un tableau est un pointeur constant sur
le premier élément du tableau.
int tab[5]={11,12,13,14,15} ;
tab[i] (cid:1) *(tab+i)
&tab[i] (cid:1) (tab+i)
tab
11
12
13
14
15
F800
F810
F820
F830
F840
indice
0
1
2
3
4
Dans cet exemple :
tab (cid:1) tab+0 (cid:1) &tab[0] : F800
tab+1 (cid:1) &tab[1] : F810
tab+2 (cid:1) &tab[2] : F820
tab+3 (cid:1) &tab[3] : F830
tab+4 (cid:1) &tab[4] : F840
tab (cid:1) (tab+0) (cid:1) tab[0] : 11
*(tab+1) (cid:1) tab[1] : 12
*(tab+2) (cid:1) tab[2] : 13
*(tab+3) (cid:1) tab[3] : 14
*(tab+4) (cid:1) tab[4] : 15
&tab[i] (cid:1)(cid:1)(cid:1)(cid:1) (tab+i)
tab[i] (cid:1)(cid:1)(cid:1)(cid:1) *(tab+i)
Mme Wiem Yaiche Elleuch
les pointeurs
Page 3
ATTENTION
Dans les exemples ci-dessus, tab n’a pas changé de valeur (sa valeur est toujours F800).
Exemple 2 : utilisation d’un tableau tab et d’un pointeur q
int tab[5]={11,12,13,14,15} ;
int *q ;
q=tab ;
q
F800
tab
11
12
13
14
15
F800
0
F810
1
F820
F830
F840
2
3
4
q (cid:1)(cid:1)(cid:1)(cid:1) &tab[0] (cid:1)(cid:1)(cid:1)(cid:1) tab+0 (cid:1)(cid:1)(cid:1)(cid:1) tab :F800
*q : 11
q+1 : F810 // q pointe toujours sur la case d’indice 0
*(q+1) : 12
q+4 : F840 // q pointe toujours sur la case d’indice 0
*(q+4) : 15
Publicité
Exemple 3
int tab[5]={11,12,13,14,15} ;
int *q ;
q=tab+2 ;
q
F820
tab
11
12
13
14
15
F800
0
F810
1
F820
F830
F840
2
3
4
q :F820
*q : 13
q+1 : F830 // q pointe toujours sur la case d’indice 2
*(q+1) : 14
q-2 : F800 // q pointe toujours sur la case d’indice 2
*(q-2) : 11
Exemple 4
int tab[5]={11,12,13,14,15} ;
int *q ;
q=tab ;
q++ ;
q
F810
tab
11
12
13
14
15
F800
0
F810
1
F820
F830
F840
2
3
4
Mme Wiem Yaiche Elleuch
les pointeurs
Page 4
q :F810
*q : 12
q+1 : F820 // q pointe toujours sur la case d’indice 1
*(q+1) : 13
q-1 : F800 // q pointe toujours sur la case d’indice 1
*(q-1) : 11
Exemple 5 : Dans les exemples suivants, q pointe sur les différentes cases du tableau.
int tab[5]={11,12,13,14,15} ;
int *q ;
q=tab ;
q :F810
q++ ;
q
F810
q
F810
q :F810
q+=3 ; (cid:1)(cid:1)(cid:1)(cid:1) q=q+3 ;
q
F810
q :F810
q-=2 ; (cid:1)(cid:1)(cid:1)(cid:1) q=q-2 ;
q
F810
tab
11
12
13 14 15
F800
0
F810
1
F820
F830
F840
2
3
4
Publicité
tab
11
12
13 14 15
F800
0
F810
1
F820
F830
F840
2
3
4
tab
11
12
13 14 15
F800
0
F810
1
F820
F830
F840
2
3
4
tab
11
12
13 14 15
F800
0
F810
1
F820
F830
F840
2
3
4
Mme Wiem Yaiche Elleuch
les pointeurs
Page 5
Résumé
En déclarant un tableau tab de type int et un pointeur q sur int,
int tab[10];
int *q;
l'instruction:
q = tab; est équivalente à q = &tab[0];
Si q pointe sur une composante quelconque d'un tableau, alors q+1 pointe sur la composante
suivante. Plus généralement,
q+i pointe sur la i-ième composante après q et
q-i pointe sur la i-ième composante avant q.
Ainsi, après l'instruction,
q = tab;
le pointeur q pointe sur tab[0], et
*(q+1) désigne le contenu de tab[1]
*(q+2) désigne le contenu de tab[2]
...
*(q+i) désigne le contenu de tab[i]
...
Remarque
q+i n'adresse pas le i-ième octet après q, mais la i-ième composante après q.
En C, le compilateur peut calculer automatiquement l'adresse de l'élément q+i en ajoutant à
q la grandeur d'une composante multipliée par i. Ceci est possible, parce que:
- chaque pointeur est limité à un seul type de données, et
- le compilateur connaît le nombre d'octets des différents types.
Exemple
Soit A un tableau contenant des éléments du type float et P un pointeur sur float:
float tab[20], X;
float *q;
Après les instructions,
q = tab;
X = *(q+9);
X contient la valeur du 10-ième élément de tab, (c.-à-d. celle de tab[9]). Une donnée du
type float ayant besoin de 4 octets, le compilateur obtient l'adresse q+9 en ajoutant 9 * 4 =
36 octets à l'adresse dans q.
Attention !
Il existe toujours une différence essentielle entre un pointeur et le nom d'un tableau:
- Un pointeur est une variable, donc des opérations comme q = tab ou q++ sont permises.
- Le nom d'un tableau est une constante, donc des opérations comme tab = q ou tab++ sont
impossibles.
6. Formalisme tableau et formalisme pointeur
Il est facile de 'traduire' un programme écrit à l'aide du 'formalisme tableau' dans un
programme employant le 'formalisme pointeur'.
Mme Wiem Yaiche Elleuch
les pointeurs
Page 6
Exemple
programme de remplissage et d’affichage d’un tableau d’entiers
#include <stdio.h>
void main ( )
Publicité
{
int tab[50];
int i,n;
printf("saisir la taille du tableau ");
scanf("%d", &n);
for (i=0; i<n; i++)
scanf("%d", &tab[i]);
for (i=0; i<n; i++)
printf("l'element d'indice %d est %d \n",i, tab[i]);
}
Nous pouvons remplacer systématiquement la notation tab [i] par *(tab + i), ce qui conduit
à ce programme:
Formalisme pointeur
#include <stdio.h>
void main ( )
{
int tab[50];
int i,n;
printf("saisir la taille du tableau ");
scanf("%d", &n);
for (i=0; i<n; i++)
scanf("%d", tab+i);
for (i=0; i<n; i++)
printf("l'element d'indice %d est %d \n",i, *(tab+i));
}
7. Arithmétique des pointeurs
Comme les pointeurs jouent un rôle si important, le langage C soutient une série
d'opérations arithmétiques sur les pointeurs. Le confort de ces opérations en C est basé sur
le principe suivant:
Toutes les opérations avec les pointeurs tiennent compte automatiquement du type et de
la grandeur des objets pointés.
- Affectation par un pointeur sur le même type
Soient P1 et P2 deux pointeurs sur le même type de données, alors l'instruction
P1 = P2;
fait pointer P1 sur le même objet que P2
- Addition et soustraction d'un nombre entier
Si P pointe sur l'élément A[i] d'un tableau, alors
P+n pointe sur A[i+n]
Mme Wiem Yaiche Elleuch
les pointeurs
Page 7
P-n pointe sur A[i-n]
- Incrémentation et décrémentation d'un pointeur
Si P pointe sur l'élément A[i] d'un tableau, alors après l'instruction
P++; P pointe sur A[i+1]
P+=n; P pointe sur A[i+n]
P--; P pointe sur A[i-1]
P-=n; P pointe sur A[i-n]
Domaine des opérations
L'addition, la soustraction, l'incrémentation et la décrémentation sur les pointeurs sont
seulement définies à l'intérieur d'un tableau. Si l'adresse formée par le pointeur et l'indice
sort du domaine du tableau, alors le résultat n'est pas défini.
Exemples
int A[10];
int *P;
P = A+9; / dernier élément -> légal /
P = A+11; / dernier élément + 2 -> illégal /
P = A-1; / premier élément - 1 -> illégal /
- Soustraction de deux pointeurs
Soient P1 et P2 deux pointeurs qui pointent dans le même tableau:
P1-P2 fournit le nombre de composantes comprises entre P1 et P2.
Le résultat de la soustraction P1-P2 est
- négatif, si P1 précède P2
- zéro,
- positif, si P2 precède P1
- indéfini, si P1 et P2 ne pointent pas dans le même tableau
si P1 = P2
Plus généralement, la soustraction de deux pointeurs qui pointent dans le même tableau est
équivalente à la soustraction des indices correspondants.
- Comparaison de deux pointeurs
On peut comparer deux pointeurs par <, >, <=, >=, ==, !=.
La comparaison de deux pointeurs qui pointent dans le même tableau est équivalente à la
comparaison des indices correspondants. (Si les pointeurs ne pointent pas dans le même
tableau, alors le résultat est donné par leurs positions relatives dans la mémoire).
Programme de remplissage et d’affichage d’un tableau, en utilisant un pointeur q
#include <stdio.h>
void main ( )
{
int tab[50];
int i,n, *q;
printf("saisir la taille du tableau ");
scanf("%d", &n);
Mme Wiem Yaiche Elleuch
les pointeurs
Page 8
for (q=tab; q<tab+n; q++)
scanf("%d", q);
for (q=tab; q<tab+n; q++)
printf("l'element d'indice %d est %d \n",i, *q);
}
Mme Wiem Yaiche Elleuch
les pointeurs
Page 9