Une variable de type pointeur est une variable dont le contenu (adresse) peut indiquer l'emplacement en mémoire d'une autre variable, créée dynamiquement lors de l'exécution et ayant un type de base précis (objet pointé). Ceci constitue la principale différence entre la notion de pointeur dans un langage de haut niveau et la notion d'adresse en assembleur.
On peut décrire les pointeurs en terme de type abstrait de la
manière suivante :
comparer deux pointeurs de même type de base pour savoir s'ils permettent d'accéder au même objet.
Ce modèle ne spécifie pas ce qu'il advient d'un éventuel objet précédemment accessible à l'aide d'un pointeur lorsque l'on demande la création d'un nouvel objet accessible à l'aide de ce même pointeur sans avoir détruit, au préalable, l'objet précédemment accessible. Il ne spécifie pas non plus ce qui se passe si l'on essaye d'accéder à l'objet sensé être accessible à l'aide d'un pointeur si l'on n'a jamais associé d'objet à ce pointeur, ni indiqué l'absence d'objet accessible (pas d'initialisation du pointeur).
Dans ce qui suit, nous allons voir la manière dont les pointeurs sont implantés en Pascal. La déclaration a la forme :
VAR P: ^TypeDeBase;
Si l'on désire qu'un pointeur n'indique l'emplacement d'aucun objet (primitive 3), on peut lui affecter la constante prédéfinie NIL (quel que soit le type de base).
Lorsqu'une variable de type pointeur est déclarée dans un programme ou une procédure, le contenu (adresse) est indéterminé au moment de l'activation du programme ou de la procédure (pas forcément NIL). Pour définir le contenu d'une variable de type pointeur, on a trois possibilités:
La procédure NEW (primitive 1) a pour tâche :
Après l'appel, on aura donc deux objets accessibles :
L'opérateur postfixé "^" permet d'implanter les primitives 5 et 6; la 5 en affectant une valeur à P^ (P^ := valeur_de_type_TypeDeBase) et la 6 en utilisant P^ dans une expression (par exemple dans une expression logique : if P^ = valeur_de_type_TypeDeBase then . . . ).
La procédure DISPOSE (primitive 2) a pour tâche :
Si l'on utilise l'affectation pour redéfinir le contenu d'une variable de type pointeur (primitive 4), il faut bien faire attention au cas où la variable pointait préalablement sur un objet en mémoire. Cet objet pourrait bien ne plus être accessible par le programme tout en continuant à occuper de la place en mémoire. On utilisera préalablement la procédure DISPOSE (primitive 2), qui libérera la place et mettra le pointeur à NIL. Ceci peut être illustré de la manière suivante :
Fig. 7.1. Effet de l'affectation sur un pointeur
Dans le même ordre d'idées, si une procédure possède une variable locale (de type pointeur) qui pointe vers une structure dynamique, il faut s'assurer, avant de sortir de la procédure, soit que cette structure est accessible autrement que par la variable locale, soit que l'on libère la place occupée par l'objet pointé. La récupération automatique de la place mémoire occupée par les variables locales de la procédure n'implique en effet pas la destruction des objets pointés.
L'affectation permet à deux variables de type pointeur de pointer vers le même objet en mémoire (primitive 4). Si l'on désire qu'un de ces deux pointeurs ne pointe plus vers rien, on utilisera l'affectation de la valeur NIL (primitive 3) et non pas la procédure DISPOSE (primitive 2), car il faut que l'objet pointé continue d'exister puisqu'une autre variable pointe aussi vers lui.
Lorsqu'un pointeur est passé en paramètre à une procédure, le passage par valeur empêche toute modification du pointeur mais pas de l'objet pointé. L'objet pointé peut donc être malencontreusement modifié, même si les apparences ne le montrent pas explicitement.
Il est à noter que dans des langages de programmation tels que Pascal, où les structures dynamiques doivent être gérées explicitement à l'aide de pointeurs, il est difficile de manipuler ces structures dynamiques de manière globale, par exemple pour copier une structure dans sa totalité ou concaténer deux structures en une.
Site Hosting: Bronco