Variables et constantes typées
Une variable est un identificateur marquant une valeur pouvant changer.
Déclaration de variable
Une déclaration de variable est une liste d'identificateurs désignant de nouvelles variables et leurs types.
Le type spécifié pour la(les) variable(s) peut être un identificateur de type précédemment déclaré dans une partie de déclaration de type dans le même bloc, dans un bloc englobant ou dans une unité; il peut également s'agir d'une nouvelle définition de type. Lorsqu'un identificateur est spécifié dans la liste d'identificateurs d'une déclaration de variable, cet identificateur est un identificateur de variable pour le bloc dans lequel la déclaration se produit. La variable peut alors être référencée dans tout le bloc, à moins que l'identifiant ne soit redéclaré dans un bloc fermé. La redéclaration crée une nouvelle variable en utilisant le même identifiant, sans affecter la valeur de la variable d'origine. Voici un exemple de partie de déclaration de variable :
Les variables déclarées en dehors des procédures et des fonctions sont appelées variables globales et résident dans le segment de données. Les variables déclarées dans les procédures et les fonctions sont appelées variables locales et résident dans le segment de pile.
Le segment de données
La taille maximale du segment de données est de 65 520 octets. Lorsqu'un programme est lié (cela se produit automatiquement à la fin de la compilation d'un programme), les variables globales de toutes les unités utilisées par le programme, ainsi que les propres variables globales du programme, sont placées dans le segment de données. Si vous avez besoin de plus de 65 520 octets de données globales, vous devez allouer les structures plus grandes en tant que variables dynamiques.
Le système de pile
La taille du segment de pile est définie via une directive de compilation $M - elle peut être comprise entre 1 024 et 65 520 octets. La taille de segment de pile par défaut est de 16 384 octets. Chaque fois qu'une procédure ou une fonction est activée (appelée), elle alloue un ensemble de variables locales sur la pile. À la sortie, les variables locales sont supprimées. A tout moment lors de l'exécution d'un programme, la taille totale des variables locales allouées par les procédures et fonctions actives ne peut pas dépasser la taille du segment de pile. La directive du compilateur $S est utilisée pour inclure des vérifications de dépassement de capacité de pile dans le code. Dans l'état par défaut {$S+}, du code est généré pour vérifier le débordement de pile au début de chaque procédure et fonction. Dans l'état {$S-}, aucune vérification de ce type n'est effectuée. Un débordement de pile peut provoquer un plantage du système, donc ne désactivez pas les vérifications de pile à moins d'être absolument sûr qu'un débordement ne se produira jamais.
Variables absolues
Les variables peuvent être déclarées comme résidant à des adresses mémoire spécifiques et sont alors appelées variables absolues. La déclaration de ces variables doit inclure une clause absolue suivant le type :
La liste d'identificateurs de la déclaration de variable ne peut spécifier qu'un seul identificateur lorsqu'une clause absolue est présente. La première forme de la clause absolue spécifie le segment et le déplacement (appelé Offset en anglais) auxquels la variable doit résider :
La première constante spécifie la base du segment et la seconde spécifie le déplacement (appelé Offset en anglais) dans ce segment. Les deux constantes doivent être comprises entre $0000 et $FFFF (0 à 65 535). Le deuxième format de la clause absolue est utilisée pour déclarer une variable au-dessus d'une autre variable, ce qui signifie qu'elle déclare une variable résidant à la même adresse mémoire qu'une autre variable :
Cette déclaration spécifie que la variable StrLen et LongueurDeChaine doivent commencer à la même adresse que la variable Chaine, et comme le premier octet d'une variable chaîne contient la longueur dynamique de la chaîne de caractères, StrLen contiendra la longueur de Chaine.
Références variables
Une référence de variable permet d'indiquer l'un des éléments suivants :
- Une variable
- Une composante d'une variable de type structuré ou chaîne de caractères
- Une variable dynamique pointée par une variable de type pointeur
Voici la syntaxe d'une référence de variable :
La syntaxe d'une référence de variable autorise une expression calculant une valeur de type pointeur. L'expression doit être suivie d'un qualificatif déréférençant la valeur du pointeur (ou indexe la valeur du pointeur si la syntaxe étendue est activée avec la directive {$X+}) pour produire une référence de variable réelle.
Qualificateurs
Une référence de variable peut contenir zéro ou plusieurs qualificateurs modifiant la signification de la référence de variable.
Un identificateur de tableau sans qualificateur, par exemple, fait référence au tableau entier :
- Resultats
Un identificateur de tableau suivi d'un index désigne une composante spécifique du tableau - dans ce cas, une variable structurée :
- Resultats[Courant + 1]
Avec un composante étant un enregistrement ou un objet, l'index peut être suivi d'un désignateur de champ. Ici, l'accès variable signifie un champ spécifique dans une composante de tableau spécifique :
- Resultats[Courant + 1].Donnees
L'indicateur de champ dans un champ de pointeur peut être suivi du symbole de pointeur (^) pour différencier le champ de pointeur de la variable dynamique vers laquelle il pointe :
- Resultats[Courant + 1].Donnees^
Si la variable pointée est un tableau, des index peuvent être ajoutés pour désigner les composantes de ce tableau :
- Resultats[Courant + 1].Donnees^[J]
Tableaux, chaînes et index
Une composante spécifique d'une variable de tableau est désigné par une référence de variable faisant référence à la variable de tableau, suivie d'un index spécifiant la composante. Un caractère spécifique dans une variable chaîne de caractères est désigné par une référence de variable faisant référence à la variable chaîne de caractères, suivie d'un index spécifiant la position du caractère.
Les expressions d'index sélectionnent des composantes dans chaque dimension correspondante du tableau. Le nombre d'expressions ne peut pas dépasser le nombre de types d'index dans la déclaration de tableau. En outre, le type de chaque expression doit être compatible avec l'affectation avec le type d'index correspondant. Lors de l'indexation d'un tableau multidimensionnel, plusieurs index ou plusieurs expressions dans un index peuvent être utilisés de manière interchangeable. Par exemple :
- Matrice[I][J]
est le même chose que
- Matrice[I,J]
Vous pouvez indexer une variable chaîne de caractères avec une seule expression d'index, dont la valeur doit être comprise entre 0..N, où N est la taille déclarée de la chaîne de caractères. Elle accède à un caractère de la valeur de chaîne de caractères, avec le type Char donné à cette valeur de caractère. Le premier caractère d'une variable de chaîne de caractères (à l'index 0) contient la longueur dynamique de la chaîne de caractères; autrement dit, Length(S) est identique à Ord(S[0]). Si une valeur est affectée à l'attribut de longueur, le compilateur ne vérifie pas si cette valeur est inférieure à la taille déclarée de la chaîne de caractères. Il est possible d'indexer une chaîne de caractères au-delà de sa longueur dynamique actuelle. Les caractères lus sont aléatoires et les affectations au-delà de la longueur actuelle n'affectent pas la valeur réelle de la variable chaîne de caractères. Lorsque la syntaxe étendue est activée (à l'aide de la directive du compilateur {$X+}), une valeur de type PChar peut être indexée avec une seule expression d'index de type de données Word. L'expression d'index spécifie un déplacement à ajouter au pointeur de caractère avant qu'il ne soit déréférencé pour produire une référence de variable de type de données Char.
Enregistrements et désignateurs de champ
Un champ spécifique d'une variable d'enregistrement est désigné par une référence de variable faisant référence à la variable d'enregistrement, suivie d'un désignateur de champ spécifiant le champ.
Voici des exemples d'indicateur de champ :
- Aujourdhui.Annee
- Resultats[1].Compteur
- Resultats[1].Quand.Mois
Dans une instruction avec une instruction With, un indicateur de champ n'a pas à être précédé d'une référence de variable à son enregistrement contenant.
Désignateurs de composantes d'objets
Le format d'un identificateur de composante d'objet est le même que celui d'un identificateur de champ d'enregistrement; c'est-à-dire qu'il se compose d'une instance (une référence de variable), suivie d'un point et d'un identificateur de composante. Un désignateur de composante désignant une méthode est appelé un désignateur de méthode. Une instruction with peut être appliquée à une instance d'un type d'objet. Dans ce cas, l'instance et la période peuvent être omises lors du référencement des composantes du type d'objet. L'instance et le point peuvent également être omis dans n'importe quel bloc de méthode, et lorsqu'ils le sont, l'effet est le même que si Self et un point étaient écrits avant la référence de la composante.
Pointeurs et variables dynamiques
La valeur d'une variable de pointeur est soit NIL, soit l'adresse d'une variable dynamique. La variable dynamique pointée par une variable de pointeur est référencée en écrivant le symbole de pointeur (^) après la variable de pointeur. Vous créez des variables dynamiques et leurs valeurs de pointeur avec les procédures New et GetMem. Vous pouvez utiliser l'opérateur @ (adresse de) et la fonction Ptr pour créer des valeurs de pointeur étant traitées comme des pointeurs vers des variables dynamiques. Le NIL ne pointe vers aucune variable. Les résultats ne sont pas définis si vous accédez à une variable dynamique lorsque la valeur du pointeur est nulle ou non définie. Voici des exemples de références à des variables dynamiques :
- P1^
- P1^.Sibling^
- Resultats[1].Donnees^
Castre de type variable
Une référence de variable d'un type peut être transformée en une référence de variable d'un autre type via un castre (transtypage) de variable.
Lorsqu'un castre de variable est appliqué à une référence de variable, la référence de variable est traitée comme une instance du type spécifié par l'identificateur de type. La taille de la variable (le nombre d'octets occupés par la variable) doit être la même que la taille du type désigné par l'identificateur de type. Un castre de variable peut être suivi d'un ou plusieurs qualificateurs, comme le permet le type spécifié.
Voici des exemples de castre de variables :
- Type
- TByteRec=Record
- _Low,_High:Byte;
- End;
-
- TWordRec=Record
- _Low,_High:Word;
- End;
-
- TPtrRec=Record
- _Ofs,_Seg:Word;
- End;
-
- PByte=^Byte;
-
- Var
- B:Byte;
- W:Word;
- L:LongInt;
- P:Pointer;
-
- BEGIN
- W:=$1234;
- B:=TByteRec(W)._Low;
- TByteRec(W)._High:=0;
- L:=$12345678;
- W:=TWordRec(L)._Low;
- B:=TByteRec(TWordRec(L)._Low)._High;
- B:=PByte(L)^;
- P:=Ptr($40,$49);
- W:=TPtrRec(P)._Seg;
- Inc(TPtrRec(P)._Ofs,4);
- END.
Notez l'utilisation du type TByteRec pour accéder aux octets de poids faible et de poids fort d'un mot. Cela correspond aux fonctions intégrées Lo et Hi, sauf qu'un castre de variable peut également être utilisé sur le côté gauche d'une affectation. Observez également l'utilisation des types TWordRec et TPtrRec pour accéder aux mots de poids faible et de poids fort d'un entier long et aux parties déplacement (offset) et segment d'un pointeur.
Le Turbo Pascal prend entièrement en charge les castres de variables impliquant des types procéduraux. Par exemple, étant donné les déclarations :
vous pouvez construire les affectations suivantes :
- F:=Func(P); { Attribuer une valeur procédurale dans P à F }
- Func(P):=F; { Attribuer une valeur procédurale dans F à P }
- @F:=P; { Attribuer la valeur du pointeur dans P à F }
- P:=@F; { Attribuer la valeur du pointeur dans F à P }
- N:=F(N); { Fonction d'appel via F }
- N:=Func(P)(N); { Fonction d'appel via P }
En particulier, notez que l'opérateur d'adresse (@), lorsqu'il est appliqué à une variable procédurale, peut être utilisé sur le côté gauche d'une affectation. Notez également le castre sur la dernière ligne pour appeler une fonction via une variable de pointeur.
Constantes typées
Les constantes typées peuvent être comparées à des variables-variables initialisées dont les valeurs sont définies à l'entrée de leur bloc. Contrairement à une constante non typée, la déclaration d'une constante typée spécifie à la fois le type et la valeur de la constante.
Les constantes typées peuvent être utilisées exactement comme des variables du même type et peuvent apparaître à gauche dans une instruction d'affectation. Notez que les constantes typées ne sont initialisées qu'une seule fois, au début d'un programme. Ainsi, pour chaque entrée d'une procédure ou d'une fonction, les constantes typées déclarées localement ne sont pas réinitialisées.
En plus d'une expression constante normale, la valeur d'une constante typée peut être spécifiée à l'aide d'une expression d'adresse constante. Une expression d'adresse constante est une expression impliquant de prendre l'adresse, le déplacement (Offset) ou le segment d'une variable globale, d'une constante typée, d'une procédure ou d'une fonction. Les expressions à adresse constante ne peuvent pas référencer des variables locales (basées sur la pile) ou dynamiques (basées sur le tas), car leurs adresses ne peuvent pas être calculées au moment de la compilation.
Constantes de type simple
Déclarer une constante typée en tant que type simple spécifie la valeur de la constante :
Comme mentionné précédemment, la valeur d'une constante typée peut être spécifiée à l'aide d'une expression d'adresse constante, c'est-à-dire une expression qui prend l'adresse, le déplacement ou le segment d'une variable globale, une constante typée, une procédure ou une fonction. Par exemple :
Parce qu'une constante typée est en fait une variable avec une valeur constante, elle ne peut pas être échangée avec des constantes ordinaires. Par exemple, il ne peut pas être utilisé dans la déclaration d'autres constantes ou de types :
La déclaration TVector n'est pas valide, car Min et Max sont des constantes typées.
Constantes de type chaîne de caractères
La déclaration d'une constante typée de type chaîne précise la longueur maximale de la chaîne de caractères et sa valeur initiale :
Constantes de type structuré
La déclaration d'une constante de type structuré précise la valeur de chacun des composantes de la structure. Le Turbo Pascal prend en charge la déclaration de constantes de type tableau, enregistrement, objet et ensemble. Les constantes de type fichier et les constantes de type tableau, enregistrement et objet contenant des composantes de type fichier ne sont pas autorisées.
Constantes de type tableau
La déclaration d'une constante de type tableau spécifie les valeurs des composants. Les valeurs sont mises entre parenthèses et séparées par des virgules.
Voici un exemple de constante de type tableau :
Cet exemple définit la constante de tableau StatStr, pouvant être utilisée pour convertir des valeurs de type TStatus en leurs représentations de chaîne de caractères correspondantes. Voici les composantes de StatStr :
StatStr[Active] = 'Actif'StatStr[Passive] = 'Passif'
StatStr[Waiting] = 'Attente'
Le type de composante d'une constante matricielle peut être de n'importe quel type, à l'exception d'un type de fichier. Les constantes de type chaîne de caractères compressées (tableaux de caractères) peuvent être spécifiées à la fois sous forme de caractères simples et sous forme de chaînes de caractères. La définition :
peut être exprimé plus commodément comme :
Lorsque la syntaxe étendue est activée (à l'aide d'une directive de compilateur {$X+}), un tableau de caractères de base zéro peut être initialisé avec une chaîne plus courte que la longueur déclarée du tableau. Par exemple :
Dans de tels cas, les caractères restants sont définis sur NULL (#0) et le tableau contient effectivement une chaîne de caractères terminée par NULL. Les constantes de tableau multidimensionnel sont définies en enfermant les constantes de chaque dimension dans des ensembles distincts de parenthèses, séparés par des virgules. Les constantes les plus à l'intérieur correspondent aux dimensions les plus à droite. La déclaration :
fournit un tableau Maze initialisé avec les valeurs suivantes :
Maze[0, 0, 0] = 0Maze[0, 0, 1] = 1
Maze[0, 1, 0] = 2
Maze[0, 1, 1] = 3
Maze[1, 0, 0] = 4
Maze[1, 0, 1] = 5
Maze[1, 1, 0] = 6
Maze[1, 1, 1] = 7
Constantes de type enregistrement
La déclaration d'une constante de type enregistrement spécifie l'identificateur et la valeur de chaque champ, entre parenthèses et séparés par des points-virgules.
Voici des exemples de constantes d'enregistrement :
- Type
- TPoint=Record
- X,Y:Real;
- End;
- TVector=Array[0..1] of Point;
- TMonth=(Jan,Feb,March,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,December);
- TDate=Record
- D:1..31;
- M:Month;
- Y:1800..9999;
- End;
- Const
- _Origin:TPoint=(X:0.0;Y:0.0);
- _Line:TVector=((X:-3.1;Y:1.5),(X:5.8;Y:3.0));
- _SomeDay:TDate=(D:2;M:December;Y:1960);
Les champs doivent être spécifiés dans le même ordre qu'ils apparaissent dans la définition du type d'enregistrement. Si un enregistrement contient des champs de types de fichiers, les constantes de ce type d'enregistrement ne peuvent pas être déclarées. Si un enregistrement contient une variante, seuls les champs de la variante sélectionnée peuvent être spécifiés. Si la variante contient un champ de balise, alors sa valeur doit être spécifiée.
Constantes de type objet
La déclaration d'une constante de type objet utilise la même syntaxe que la déclaration d'une constante de type enregistrement. Aucune valeur n'est, ou ne peut être, spécifiée pour les composantes de méthode. Voici des exemples de constantes de type d'objet :
Constantes de type ensemble
Tout comme une constante de type simple, la déclaration d'une constante de type ensemble spécifie la valeur de l'ensemble à l'aide d'une expression constante. Voici quelques exemples :
Constantes de type de pointeur
La déclaration d'une constante de type pointeur utilise une expression d'adresse constante pour spécifier la valeur du pointeur. Quelques exemples suivent :
- Type
- TDirection=(Left, Right, Up, Down);
- TStringPtr=^String;
- PNode=^TNode;
- TNode=Record
- Next:PNode;
- Symbol:TStringPtr;
- Value:TDirection;
- End;
-
- Const
- S1:String[3]='BAS';
- S2:String[4]='HAUT';
- S3:String[6]='DROITE';
- S4:String[6]='GAUCHE';
- N1:TNode = (Next:NIL;Symbol:@S1;Value:Down);
- N2:TNode = (Next:@N1;Symbol:@S2;Value:Up);
- N3:TNode = (Next:@N2;Symbol:@S3;Value:Right);
- N4:TNode = (Next:@N3;Symbol:@S4;Value:Left);
- DirectionTable:PNode=@N4;
Lorsque la syntaxe étendue est activée (à l'aide d'une directive de compilation {$X+}), une constante typée de type PChar peut être initialisée avec une constante chaîne de caractères. Par exemple :
Le résultat est que le pointeur pointe maintenant vers une zone de mémoire contenant une copie terminée par zéro du littéral de chaîne de caractères.
Constantes de type procédural
Une constante de type procédural doit spécifier l'identifiant d'une procédure ou d'une fonction compatible avec l'affectation avec le type de la constante, ou elle doit spécifier la valeur NIL.
Voici un exemple :