Un pointeur ne servirait strictement à rien s'il n'y avait pas de possibilité d'accéder à l'adresse d'une variable ou d'une fonction (on ne pourrait alors pas l'initialiser) ou s'il n'y avait pas moyen d'accéder à l'objet référencé par le pointeur (la variable pointée ne pourrait pas être manipulée ou la fonction pointée ne pourrait pas être appelée).
Ces deux opérations sont respectivement appelées indirection
et déréférencement. Il existe deux opérateurs permettant de récupérer l'adresse
d'un objet et d'accéder à l'objet pointé. Ces opérateurs sont respectivement &
et *
.
Il est très important de s'assurer que les pointeurs que l'on manipule sont tous
initialisés (c'est-à-dire contiennent l'adresse d'un objet valide, et pas n'importe quoi). En effet,
accéder à un pointeur non initialisé revient à lire ou, plus grave encore, à écrire dans la mémoire
à un endroit complètement aléatoire (selon la valeur initiale du pointeur lors de sa création). En général,
on initialise les pointeurs dès leur création, ou, s'ils doivent être utilisés ultérieurement, on
les initialise avec le pointeur nul. Cela permettra de faire ultérieurement des tests sur la validité
du pointeur ou au moins de détecter les erreurs. En effet, l'utilisation d'un pointeur initialisé
avec le pointeur nul génère souvent une faute de protection du programme, que tout bon débogueur est
capable de détecter. Le pointeur nul se note NULL
.
Note :
NULL
est une macro définie dans le fichier d'en-tête stdlib.h. En C, elle représente la valeur d'une adresse invalide. Malheureusement, cette valeur peut ne pas être égale à l'adresse 0 (certains compilateurs utilisent la valeur -1 pourNULL
par exemple). C'est pour cela que cette macro a été définie, afin de représenter, selon le compilateur, la bonne valeur. Voir le Chapitre 5 pour plus de détails sur les macros et sur les fichiers d'en-tête.La norme du C++ fixe la valeur nulle des pointeurs à 0. Par conséquent, les compilateurs C/C++ qui définissent
NULL
comme étant égal à -1 posent un problème de portabilité certain, puisque un programme C qui utiliseNULL
n'est plus valide en C++. Par ailleurs, un morceau de programme C++ compilable en C qui utiliserait la valeur 0 ne serait pas correct en C.Il faut donc faire un choix : soit utiliser
NULL
en C et 0 en C++, soit utiliserNULL
partout, quitte à redéfinir la macroNULL
pour les programmes C++ (solution qui me semble plus pratique).
Exemple 4-1. Déclaration de pointeurs
int i=0; /* Déclare une variable entière. */ int *pi; /* Déclare un pointeur sur un entier. */ pi=&i; /* Initialise le pointeur avec l'adresse de cette variable. */ *pi = *pi+1; /* Effectue un calcul sur la variable pointée par pi, c'est-à-dire sur i lui-même, puisque pi contient l'adresse de i. */ /* À ce stade, i ne vaut plus 0, mais 1. */
Il est à présent facile de comprendre pourquoi il faut répéter l'étoile dans la déclaration de plusieurs pointeurs :
int *p1, *p2, *p3;signifie syntaxiquement : p1, p2 et p3 sont des pointeurs d'entiers, mais aussi *p1, *p2 et *p3 sont des entiers.
Si l'on avait écrit :
int *p1, p2, p3;seul p1 serait un pointeur d'entier. p2 et p3 seraient des entiers.
L'accès aux champs d'une structure par le pointeur sur cette structure se fera
avec l'opérateur '->
', qui remplace '(*).'.
Précédent | Sommaire | Suivant |
Notion de pointeur | Niveau supérieur | Notion de référence |