« Structures de données/Pointeurs » : différence entre les versions
Ligne 1 : | Ligne 1 : | ||
== La mémoire dynamique == |
|||
En plus d'allouer à chaque programme une mémoire statique, le système d'exploitation alloue au programme P une mémoire dynamique. Dans notre exemple avec l'inversion de deux variables notre programme n'utilise que la mémoire statique. Nous aurions pu omettre de représenter sur nos schémas cette mémoire. |
|||
La mémoire dynamique a les mêmes caractéristiques que le mémoire statique telle que décrite précédemment. Les cases sont numérotées (nous supposerons là encore sur 8 bits : de 00 à FF) |
|||
Nous allons apprendre comment utiliser cette mémoire dynamique. Et ce, avec cet outil que sont les '''pointeurs'''. |
|||
== Les pointeurs typés == |
== Les pointeurs typés == |
||
Version du 13 mai 2012 à 20:51
Les pointeurs typés
Le pointeur est un nouveau type au même titres que les entiers, les caractères, chaînes de caractères, booléens et autres abordés en algorithmique impérative.
Il convient cependant de distinguer les pointeurs typés des pointeurs non-typés (également appelés génériques). Nous allons d'abord nous pencher sur les premiers et réserver les seconds pour plus tard.
Un pointeur typé indique le type de la donnée qu'il pointe. Il y a donc des pointeurs vers des entiers, des pointeurs vers des caractères, etc. Il convient d'affecter à des variables de types pointeur vers T uniquement des expressions de types pointeur vers T (tout comme on doit assigner à une variable de type entier une expression entière).
Spécification
On déclare un pointeur vers T (T : un type) comme suit :
Lexique identifiant_du_pointeur : ^T
On accède à la valeur pointée comme suit :
identifiant_du_pointeur^
Cette expression est donc du type pointé : T
Ecrire(identifiant_du_pointeur)
afficherait l'adresse mémoire ou est stockée la donné pointée (souvent en sous la forme hexadécimale) : dans notre cours ce n'est d'aucune utilité.
Utilisation
Exemple avec des entiers
Remarque : encore une fois ce programme n'est d'aucune utilité. On pourrait en faire un équivalent sans utiliser de pointeurs. Le but est d'expliquer les mécanismes décrits précédemment.
Algorithme Exemple Lexique a : entier b : entier p1 : ^entier p2 : ^entier Début a:=1 new(p1) (* on réserve de l'espace pour stocker un entier *) p1^:=a (* stocke 1 dans la zone mémoire pointée par p1 *) ecrire(p1^) (* affiche 1 *) a:=2 ecrire(p1^) (* affiche 1 *) p2:=p1 (* p2 va pointer la zone mémoire pointée par p1 *) ecrire(p2^) (* affiche 1 *) p2^:=3 (* on place 3 dans la zone mémoire pointée par p2 *) ecrire(p1^) (* affiche 3 *) delete(p1) (* on libère la zone pointée par p1 et donc la zone pointée par p2 *) (* a se stade : plus aucune zone mémoire n'est réservée dans la mémoire dynamique *) new(p1) new(p2) p1^:=4 p2^:=p1^+1 ecrire(p2^) (* affiche 5 *) (* il est d'usage de libérer au maximum la mémoire dynamique : *) delete(p1) delete(p2) Fin
Les effets de bord
Que se passe-t-il ?
Algorithme bogue Lexique p : pointeur p_entier : ^entier p_caractere : ^caractere début new(p_entier) p_entier^:=2645 p:=p_entier p_caractere:=p (* pas de problème : on assigne une adresse mémoire à un pointeur (typé) *) (* Jusqu'ici aucun problème nous n'avons fait que des opérations permises *) ecrire(p_caractere^) (* ???? *) fin