On peut toujours utiliser dans un programme et ses sous-programmes des variables globales et des variables locales ayant le même identificateur.
L’idée d’éviter d’utiliser le même identificateur pour une variable globale et une variable locale est FAUSSE.
Un programme peut être écrit par plusieurs codeurs ; chacun se charge d’un sous-programme (ou plus).
Ces différents codeurs n’ont absolument pas besoin de savoir quelles variables globales sont utilisées dans le programme principal.
Une variable globale (déclarée par DIM) est visible partout, dans le programme principal et ses sous-programmes si et seulement si le sous-programme ne déclare pas lui-même une variable locale du même nom par DIM_LOCAL.
Sa durée de vie est celle du programme principal.
Par contre une variable locale déclarée dans un sous-programme par DIM_LOCAL n’est visible que dans ce sous-programme et elle est PRIORITAIRE sur la variable globale.
En dehors de son propre sous-programme elle n’existe plus.
Sa durée de vie est donc celle du sous-programme.
Panoramic permet d’utiliser deux sortes de sous-programmes : SUB / END_SUB et GOSUB / RETURN.
Appel d’un sous-programme SUB / END_SUB.Lorsque le programme principal (ou un sous-programme) appelle un sous-programme défini entre SUB / END_SUB, le système procède comme suit.
Le système commence tout d’abord par sauvegarder l’environnement du travail de l’appelant en mettant sur la pile (PUSH) les contenus des différents registres principaux (l’accumulateur, le compteur ordinal, le registre d’état, le pointeur de pile, etc).
Puis il dépose sur la pile une copie des variables locales sur lesquelles va travailler le sous-programme.
Si des variables globales portant les mêmes noms que des variables locales existent, elles seront purement et simplement ignorées par le sous-programme : la priorité est aux variables locales.
Arrivé à END_SUB, le système élimine la copie des variables locales (leur durée de vie s’achève ici), récupère de la pile (POP) l’ancien environnement de l’appelant en rétablissant les valeurs des registres initialement sauvegardés et continue l’exécution du programme à l’instruction qui vient juste après l’appel.
Appel d’un sous-programme par GOSUBIci le système sauvegarde sur la pile seulement la valeur du compteur ordinal qui indique l’adresse de la prochaine instruction qui suit le GOSUB.
Le système se débranche de l’appelant pour se brancher sur le sous-programme.
Toutes les variables globales dont la visibilité n’est pas éclipsée par les variables locales sont reconnues ainsi que toutes les variables locales de la SUB qui a fait l’appel.
Arrivé à RETURN, le système récupère l’adresse de retour à partir de la pile et continue son exécution et la charge dans le compteur ordinal.
Commentons le code de Oscaribout
- Code:
-
' teste avec SUB et S/P
dim procedure$ : label essai
teste()
message procedure$
end
' ---------
sub teste()
dim_local procedure$ , teste$ : procedure$ = "teste()"
teste$ =" on est dans teste()"
gosub essai
message procedure$ :' ici c'est foutu pour la variable locale
end_sub
' ---------
essai:
' normalement le s/p est une extension de ce qui l'appel
procedure$ = "essai:"
message "teste$="+teste$ :' donc ici on récupère la variable locale
return
La ligne 2 déclare une variable globale
procedure$.
A ce stade, la variable existe et comme aucune valeur ne lui est affectée, le système lui donne par défaut la chaîne vide.
La ligne 3 appelle le sous-programmes teste().
Le système sauvegarde l’environnement de travail du programme principal et se branche sur le sous-programme.
Ce dernier déclare lui aussi une variable locale
procedure$ de même nom que la variable globale et lui affecte la valeur "teste()"
La variable globale
procedure$ existe toujours mais elle est éclipsée par la variable locale de même nom, de sorte que le système ne « voit » que la variable locale.
La ligne 9 fait un appel au sous-programme
essai par l’instruction GOSUB.
Remarquez que nous sommes encore dans la SUB.
Le système mémorise l’adresse de l’instruction suivante (message essai) et se branche à
essaiCe sous-programme modifie le contenu de la variable procedure$ qui contient maintenant la valeur "essai:"
Mais de quelle variable procedure$ parle-t-on ? de la globale ou de la locale ?
Comme le sous-programme
essai : fait partie de la SUB teste() et qu’on est à l’intérieur de la SUB, c’est la variable locale qui est visée.
La variable
teste$ aussi reste visible.
L’affichage par message est tout à fait correct et c’est à ce quoi on s’attendait.
Arrivé à l’instruction
return, le système va chercher sur la pile la valeur du compteur ordinal précédemment sauvegardé, c’est ce qu’on appelle l’adresse de retour, et continue son déroulement.
Sur la ligne 10, Oscaribout a commenté ' ici c'est foutu pour la variable locale
Non, ce n’est pas foutu : le sous-programme
essai : a bien fonctionné et comme on lui a indiqué de modifier la valeur de la variable
procedure$ il a obéi comme il se doit.
Pour moi, c’est correct.
Le contraire m’aurait surpris.
NB : dans cet exemple, la variable
procedure$ déclarée comme globale, n’a jamais été utilisée ni modifiée, elle vaut toujours la chaîne vide.
Pour vous en convaincre, affichez-la par
message procedure$ juste avant le END du programme principal.
Il faut retenir qu’une variable déclarée globale existera tant que le programme principal reste en cours.
Sa visibilité peut être éclipsée par une variable locale de même nom, mais non modifiée par celle-ci.
L’existence et la visibilité d’une variable locale durent le temps de l’exécution de la SUB où elle se trouve. En dehors, elle est supprimée par le système, contrairement à une variable globale qui existe tant que le programme n’est pas terminé soit par TERMINATE soit par la fermeture par la croix ou encore si le programme ne contient pas une instruction de libération de la dite variable par FREE.
EDIT
On s’est croisé Oscaribout.
De toutes les façons cette discussion nous a permis d’échanger nos points de vue.
A+