next up previous contents index
suivant: L'opérateur & et le monter: main précédent: Bibliothèques   Table des matières   Index


Pointeurs

C++ dispose d'un type pointeur. Plus exactement, il s'agit d'un constructeur de type, noté *, qui s'applique à un type $T$ pour construire le type des pointeurs de $T$, noté $T$*. Quel que soit le type $T$, une valeur de type $T$* 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 $T$* doit être initialisé par l'adresse d'un objet ou d'une fonction de type $T$. 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 $E$ est une expression de type pointeur de $T$, alors *$E$ est une expression correctement typée de type $T$. Elle peut être placée à gauche d'une affectation, comme une variable, ce qui signifie qu'elle doit désigner un objet de type $T$.

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 *$E$ 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 $1/(1-1)$ est aussi correctement typée, mais provoquera aussi une erreur à l'exécution. Le cas le plus usuel est celui où $E$ est simplement une variable p de type pointeur de $T$ ; 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 $T$. Un pointeur initialisé à NULL << ne pointe pas >>, il ne pointe sur rien. D'où l'importance de l'initialisation pour les pointeurs.


next up previous contents index
suivant: L'opérateur & et le monter: main précédent: Bibliothèques   Table des matières   Index
R Lalement