• Aucun résultat trouvé

3 Les limites de l'approche descendante

2. Les paramètres d’une procédure

2.1 Pourquoi

Comme l'a montré l'exemple précédent, il arrive que, lors de l'analyse par affinements successifs mise en oeuvre dans la démarche descendante, des actions complexes s'avèrent extrêmement semblables, conduisant dès lors à des procédures jumelles. En réalité, la seule chose qui distingue ces procédures ce sont les variables globales consultées et modifiées.

Dans ce cas plutôt que de recommencer à plusieurs reprises la description de procédures dont les textes ne différent de l'une à l'autre que par les noms des variables mentionnées sur lesquelles les mêmes actions sont commandées, on va se contenter d'un seul texte de procédure, assortis d'un ensemble de paramètres. Le texte de la procédure mentionnera alors, au lieu de jeux de variables différents, ces paramètres. C'est lors de l'appel de procédure que chaque paramètre se verra associer une valeur ou une variable.

2.2 Comment 2.2.1 Les principes

1. Dans l'entête de la procédure, on fera suivra son identifiant (= le nom de la procédure) par la liste des divers paramètres dont on décide de la doter, liste enclose dans des parenthèses. On appelle parfois paramètres formels ceux dont les noms sont ainsi indiqués.

Chaque paramètre est caractérisé par son type (comme le sont les variables) et par son genre : valeur ou variable. Le type de chaque paramètre suit le nom (dont il est séparé par le symbole «: »). Un paramètre de genre variable est de plus (en Pascal) précédé du mot «var». Ainsi par exemple :

procedure AGIR(A: integer; B: integer; var C: integer; D: integer; var E: real; var F: real; G: real; H: real; I: integer)

Les paramètres y sont les suivants :

A de type entier (integer) de genre valeur

B de type entier (integer) de genre valeur

C de type entier (integer) de genre variable

D de type entier (integer) de genre valeur

E de type réel (real) de genre variable

F de type réel (real) de genre variable

G de type réel (real) de genre valeur

H de type réel (real) de genre valeur

I de type entier (integer) de genre valeur

Notons qu'on aurait pu regrouper certain des paramètres (comme on le fait parfois aussi pour les variables) et écrire :

procedure AGIR(A, B: integer; var C: integer; D: integer; var E, F: real; G, H: real; I: integer)

L'ordre de succession des paramètres est important, ainsi que la distinction entre le genre

valeur et le genre variable. On notera cependant que le mot «var» peut figurer à plusieurs

reprises dans la liste des paramètres.

2. Lors de l'appel de la procédure, chaque paramètre va se voir associer "quelque chose" en fonction de son genre et de son type. Cette association se fait en suivant l'ordre des paramètres formels. Ce qui est ainsi associé aux paramètres formels lors de l'appel, est souvent appelé paramètre effectif : une valeur pour les paramètres de genre valeur, une

variable pour les paramètres de genre variable.

- Les paramètres valeurs se voient associer une valeur (= une donnée) du type attendu. Comme d'habitude, cette donnée peut être décrite comme une constante, une variable ou encore une expression.

Lors de l'appel, chaque paramètre valeur donne naissance à une variable locale qui sera initialisée à l'aide de la valeur associée à ce paramètre valeur. Une variable est donc créée et la valeur indiquée lui est affectée.

A la fin de l'exécution de la procédure, ces variables disparaissent et leurs contenus deviennent donc inaccessibles.

- Les paramètres variables se voient associer une variable existant avant l'appel et accessible à l'appelant : ce sont des surnoms, portés par les variables associées jusqu'à la fin de l'exécution de la procédure. Mais, toutes les modifications apportées lors de l'exécution de la procédure (ou de procédures appelées par cette dernière) à un paramètre variable sont en réalité effectuées sur la variable préexistante associée.

A la fin de l'exécution de la procédure, le surnom correspondant au paramètre variable disparaît, mais la variable correspondante reste bien entendu disponible, avec un contenu généralement modifié.

?

S'il n'existait qu'un seul genre de paramètre, serait-il préférable que ce soit le genre valeur ou le genre variable ? Pourquoi ?

Ainsi, dans le cas de l'exemple donné ci-dessus, on pourrait avoir l' appel suivant :

AGIR(14, 2*Compteur+1,Compteur,Compteur, Facteur, Solution, 12.6, Compteur/2, 0)

l'entête de la procédure appelée étant :

procedure AGIR(A, B: integer; var C: integer; D: integer; var E, F: real; G, H: real; I: integer)

la correspondance est alors la suivante :

A B C D E F

copie copie surcharge copie surcharge surcharge

14 2*Compteur+1 Compteur Compteur Facteur Solution et

G H I

copie copie copie

12.6 Compteur/2 0

Outre d'autres variables qui auraient été par ailleurs disponibles, on se trouve en tout cas au début de l'exécution de AGIR avec les variables suivantes (en supposant que Compteur contienne 15) :

A B Compteur C D 14 31 (2*Compteur+1) 15 15 (Compteur) Facteur E Solution F G H ? ? 12.6 7.5 (Compteur/2) I 0

3. Comme on le devine, les paramètres valeurs, qui donneront naissance lors de l'appel à des variables locales dans lesquelles seront copiées des données choisies, mais qui disparaîtront à la fin de l'exécution, peuvent servir uniquement à passer de l'information à la procédure appelée; jamais le résultat du travail effectué par une procédure ne pourra être récupéré à travers un paramètre valeur.

Par contre, comme un paramètre variable n'est qu'un surnom pour désigner, pendant le temps de l'exécution de la procédure, une variable qui existait avant l'appel et continuera à exister après l'exécution (même si le surnom aura alors disparu), un paramètre variable peut servir à recueillir le résultat du travail de la procédure.

On pourrait dès lors identifier les paramètres valeurs à des manières de fournir en entrée des informations à une procédure et les paramètres variables à des possibilités de sortir des informations à l'issue de l'exécution de la procédure.

?

Voyez-vous des situations où il serait judicieux d'utiliser un paramètre variable pour simplement passer en entrée de l'information à une procédure en ne souhaitant pas recueillir quoi que ce soit au travers de ce paramètre à l'issue de l'exécution ? Quelle en est la raison ? Cette manière de procéder comporte-t-elle des risques ?

Identifier paramètre valeur avec entrée d'informations et paramètre variable avec sortie d'informations est généralement correct. Il faut noter cependant qu'un paramètre variable peut évidemment servir aussi à fournir des informations à la procédure appelée et pas seulement à en recueillir. En effet, on peut avoir commandé à l'exécutant principal ou à l'exécutant d'une procédure appelante de ranger des informations indispensables dans une variable qui sera surnommée, lors d'un appel, par un paramètre variable. L'information qui y est ainsi préalablement logée est évidemment accessible, à travers le paramètre variable, par la procédure appelée.

On peut choisir de procéder de cette manière lorsque, par exemple, un tableau de grande dimension doit être passé en entrée à une procédure. Passer les informations contenues dans ce tableau à travers un paramètre valeur provoque la création d'un tableau local à la procédure dans lequel les composantes du tableau original seront recopiées. On se trouve alors, pendant l'exécution de la procédure, avec deux gros tableaux qui vont manger une partie importante des ressources de la mémoire, le tableau local disparaissant seulement à la fin de l'exécution de la procédure. Dans un souci d'épargner la mémoire disponible, on peut choisir d'utiliser un paramètre variable qui surchargera pendant l'exécution de la procédure l'étiquette du tableau original. On n'a plus alors qu'un seul tableau à loger en mémoire pendant l'exécution de la procédure.

Il faut se rendre compte cependant que, dans cette manière de faire, toutes les manipulations effectuées sur le paramètre variable au sein de la procédure le sont en réalité sur le tableau original que ce paramètre désigne. Si donc le tableau original ne pouvait être modifié (mais seulement consulté) par la procédure, il faudra veiller à ce qu'aucun changement ne soit apporté au tableau désigné par le paramètre variable : ce serait l'original qui serait affecté par ces changements. Il s'agit d'une source d'erreur bien connue en programmation : l'effet de bord.

4. On parle souvent pour les paramètres valeurs de passage par valeur (lors de l'appel) : une variable locale est créée et une valeur lui est affectée (= une donnée y est recopiée).

Dans le cas des paramètres variables, on parle plutôt de passage par adresse; c'est non pas une valeur qui est associée au paramètre variable, mais l'adresse d'une variable

préexistante, autrement dit on précise l'emplacement (en mémoire) de la variable désignée par le paramètre variable.

2.2.2 Les détails syntaxiques en Pascal

2.2.2.1 Nécessité de prédéfinir un type explicite pour les paramètres de type structuré

Comme les variables, les paramètres, tant du genre valeur que du genre variable, peuvent être de l'un quelconque des types déjà rencontrés : entier (integer et les types dérivés dans l'implémentation Turbo Pascal : byte, word, shortint, longint), caractère (char), réel (real et single, double, extended, comp), booléen, énuméré ou intervalle.

Dans le cas de types structurés (comme un tableau, ou d'autres types que vous découvrirez plus tard comme ensemble ou enregistrement), il est cependant indispensable qu'un type explicite ait préalablement été défini. Ainsi, on ne peut pas écrire

procedure TRAITER(T: array[1..100] of real, ...)

il est indispensable d'avoir prédéfini, à un endroit du programme que la procédure appelée "connaît" (dans la partie déclaration du programme principal ou d'une procédure "ancêtre) un type explicite :

type Etagere = array[1..100] of real; pour pouvoir alors écrire

procedure TRAITER(T: Etagere, ...)

Cependant, Turbo Pascal admet des paramètres de type string, mais on ne peut en limiter la longueur possible comme dans string[40]; dans ce dernier cas il faut à nouveau avoir prédéfini un type explicite, par exemple :

type NombreRomain = string[40]

ce qui permettra de définir des paramètres de type NombreRomain15.

2.2.2.2 Importance de la concordance des types lors des appels

Nous savons que, lors de l'appel, les paramètres effectifs, valeurs (constantes, variables ou expressions) ou variables, associés aux divers paramètres formels sont simplement listés en étant séparés par des virgules, dans l'ordre où les paramètres formels correspondants sont définis dans l'entête de la procédure. Il faut évidemment être attentif à ce que le type de la valeur ou de la variable associées à chaque paramètre formel lors de l'appel coïncide.

15 Certains de ces détails syntaxiques sont susceptibles de se modifier dans certaines implémentations de Pascal : une fois de plus, si la connaissance du langage utilisé est indispensable, ce n'est pas elle qui constitue l'essentiel.

2.2.2.3 Les variables surnommées par des paramètres variables restent directement accessibles

J'ai été attentif dans les schémas proposés à illustrer le fait que les étiquettes correspondant aux paramètres variables, et qui viennent surcharger des étiquettes de variables existantes et accessibles, laissent ces dernières apparentes.

C'est qu'en effet, ces variables restent à la fois accessibles par les surnoms que constituent les paramètres variables associés, mais également directement sous leur nom. Cette possibilité ne constitue cependant pas une pratique recommandable et l'on est en droit de se demander si elle a vraiment du sens au sein d'une saine programmation.