C++ dispose d'un type pointeur. Plus exactement, il s'agit
d'un constructeur de type, noté *, qui s'applique à un type
pour construire le type des pointeurs de
, noté
*.
Quel que soit le type
, une valeur de type
* est une
adresse ou bien la constante NULL
(définie dans
<iostream>). D'un usage souvent dangereux, les opérations sur
ce type sont fortement limitées dans certains langages récents, comme
CAML ou Java (où ce type ne figure même pas).
Voici la définition, sans initialisation, d'une variable de type int*, c'est-à-dire pointeur de int :
int *ip;
Il y a plusieurs façons d'initialiser un pointeur. La plus simple est sûrement de l'initialiser par la valeur nulle :
int *ip = NULL;
Cette affectation int *ip = ... signifie en fait int* ip = ..., qui est une autre écriture permise et non *ip = ..., qui serait une erreur de type ; d'ailleurs, si l'initialisation se fait ultérieurement par affectation, on écrirait :
ip = NULL; *ip = NULL; // ERREUR
Sinon, un pointeur de type * doit être initialisé par
l'adresse d'un objet ou d'une fonction de type
. Il y a deux façons
d'obtenir l'adresse d'un objet : soit l'objet existe déjà, et C++ permet
d'obtenir son adresse grâce à l'opérateur
&
(Cf. § 70),
soit on obtient l'adresse d'un nouvel objet en le créant grâce à
l'opérateur new ou new[] (Cf. § 72).
Cette seconde façon est de loin la plus importante en C++.
int i; int *ip = &i; // ip est l'adresse de i int *q = new int; // q est l'adresse d'un nouvel int
La principale opération que l'on peut faire sur un pointeur, c'est la
déréférenciation, ce qui signifie l'accès à l'objet dont
l'adresse est la valeur du pointeur.
Si est une expression de type pointeur de
, alors *
est une expression correctement typée de type
.
Elle peut être placée à gauche d'une affectation, comme une variable, ce
qui signifie qu'elle doit désigner un objet de type
.
Cependant, l'utilisation de cette variable a de fortes chances de provoquer un << Segmentation fault >> s'il n'y a pas eu d'initialisation convenable :
int *p; *p = 4; // ERREUR : p non initialisé
Il y a dans ce cas tentative d'affecter une valeur à un objet,
*p, qui n'existe pas. On obtiendrait la même erreur si l'on
tentait de lire *p dans les mêmes conditions. Que l'expression
* soit correctement typée ne garantit absolument pas qu'elle
désigne un objet, autrement dit qu'elle pointe vers quelque chose
ou réfère à quelque chose. L'expression arithmétique
est aussi correctement typée, mais provoquera aussi une erreur à
l'exécution. Le cas le plus usuel est
celui où
est simplement une variable p de type
pointeur de
; c'est seulement quand p a été
initialisée correctement à une valeur non-nulle, que l'on peut dire que
p << pointe >>, et donc que l'on peut utiliser *p en
tant que variable de type
. Un pointeur initialisé à NULL
<< ne pointe pas >>, il ne pointe sur rien. D'où l'importance de
l'initialisation pour les pointeurs.