Section courante

A propos

Section administrative du site

Pointeurs en OSS Personal Pascal

En OSS Personal Pascal, les pointeurs ne peuvent être utilisés que pour accéder aux données ayant été allouées dynamiquement. En particulier, le Pascal standard ne fournit aucun moyen de trouver l'adresse d'une variable globale ou locale existante. Bien qu'il existe des moyens de tricher et de contourner cette restriction, comme le montrent certaines des routines de démonstration sur les disques OSS Personal Pascal, leur fonctionnement n'est pas garanti. Dans tous les cas, la probabilité qu'ils soient transportables vers d'autres versions de Pascal est au mieux faible.

Parce que l'utilisation de pointeurs est si restreinte, nous devons d'abord discuter de la façon dont Pascal alloue et désalloue des zones de données dynamiques. De plus, bien que les deux routines accomplissant ces tâches soient appelées procédures, elles violent tellement les règles de paramètres de procédure standard qu'il peut être plus susceptible de les considérer comme des types particuliers d'instructions.

NEW et DISPOSE

New(p);
Dispose(p);

La procédure New alloue une variable dynamique de "type de domaine" de p afin que la variable dynamique puisse être accédée en utilisant l'accès variable à partir de p^. Si p est un pointeur vers un type d'objet, alors ce type particulier est son type de domaine.

NOTE : La valeur de la variable dynamique est indéfinie après son affectation. Ne comptez pas sur la mémoire effacée, les chaînes de caractères ayant une longueur de zéro,...

La procédure Dispose désalloue la variable dynamique associée au pointeur p, laissant p indéfini. Dans OSS Personal Pascal, désallouer signifie simplement que l'espace utilisé par la variable dynamique est renvoyé au tas afin qu'il puisse être à nouveau alloué ultérieurement.

Référencer des variables de pointeur

Les pointeurs peuvent être comparés à d'autres pointeurs du même type de domaine, ou à la constante NIL, en utilisant les opérateurs relationnels "=" et "<>". Mais aucune autre comparaison n'est valable pour les pointeurs. Une variable pointeur peut être légalement modifiée de l'une des quatre manières suivantes. Pour chacune des manières ci-dessous, supposons que la déclaration suivante est en vigueur (et que chaque instruction est exécutée dans l'ordre donné) :

  1. VAR p,r:^INTEGER;

Vous pouvez affecter à n'importe quel pointeur la constante de pointeur prédéfinie NIL :

  1. p:=NIL;

Vous pouvez allouer un entreposage de données dynamique et l'affecter à un pointeur via la procédure NEW :

  1. NEW(p);

Vous pouvez lui affecter la valeur d'un autre pointeur du même type de domaine :

  1. r:=p;

À ce stade, vous pouvez utiliser soit "r" soit "p" pour faire référence à la zone de données obtenue via l'appel NEW. Par exemple :

  1. p^:=29;
  2. WriteLn(r^);

Cela produira les résultats attendus, comme si vous aviez codé :

  1. WriteLn(29);

Vous pouvez utiliser la procédure DISPOSE pour désallouer l'entreposage de données référencé par un pointeur :

  1. DISPOSE(r);

ATTENTION : C'est une erreur dans le Pascal standard d'utiliser les données pointées par une variable ayant été «supprimée», mais aucune méthode pour indiquer cette erreur n'est spécifiée. Pratiquement aucun compilateur Pascal ne pourrait garder une trace de toutes les variables de pointeur faisant référence au même espace alloué. Avec OSS Personal Pascal, vous pourriez obtenir une erreur «pointer out of heap» si vous essayez maintenant cette instruction :

  1. WriteLn(p^);

Mais si certains NEW ultérieurs avaient alloué ce même espace à un autre pointeur, les résultats sont imprévisibles.

Allocation dynamique des enregistrements de variantes

Lorsque vous utilisez la procédure NEW pour allouer des variables dynamiques d'un type d'enregistrement de variante, vous pouvez spécifier les variantes que vous souhaitez activer en ajoutant des paramètres supplémentaires aux procédures New et Dispose. Cela permet d'économiser de grandes quantités d'espace de tas lorsque les variantes sont de tailles très différentes.

New(p,c1,c2...cN);
Dispose(p,c1,c2...cN);

La variable p est un pointeur avec un type de domaine d'enregistrement variant. Les constantes c1 à cN sont des constantes de casse dans des niveaux de variance de plus en plus profonds pour le type d'enregistrement variant. Par exemple, considérons ces déclarations :

  1. TYPE
  2.  vtype=RECORD
  3.   fixed:Real;
  4.    CASE Boolean OF
  5.     True:(vs:String[40]);
  6. False:(vp:^vtype);
  7.    END;
  8.  END;
  9. VAR
  10.  vrec:^vtype;

Compte tenu de l'exemple, un appel à :

  1. NEW(vrec,True);

allouerait 46 octets de mémoire dynamique et la rendrait accessible via vrec^, mais un appel à :

Une fois que la variable d'enregistrement de variante dynamique est allouée, elle est soumise aux mêmes restrictions que les enregistrements de variante normalement alloués, mais avec certains dangers. Après un appel pour la variante FALSE de VREC, toute tentative d'accès à VREC^.VS peut provoquer une erreur ou des effets secondaires désagréables. Une instruction accédant de manière invalide à la variante INACTIVE, telle que :

  1. vrec^.vs:='Un simple test';

pourrait effacer des zones imprévisibles de la mémoire en dehors de l'espace alloué dynamiquement. Enfin, une restriction majeure est que vous devez disposer de la variable exactement de la même manière que vous l'avez allouée. Le plantage du système est pratiquement garanti si vous effectuez cette paire d'appels en séquence :

  1. NEW(vrec,True);
  2. DISPOSE(vrec,False);


Dernière mise à jour : Dimanche, le 19 septembre 2021