2.4.une grammaire du Pascal



Plan du chapitre:

1. Rappel de la structure d’un programme Pascal


2. Les opérateurs en pascal

     
    2.1 Les opérateurs multiplicatifs
    2.2 Les opérateurs additifs
    2.3 Les opérateurs relationnels
    2.4 Déclarations des constantes


3. Déclarations des types en Pascal
 

    3.1 Déclarations des types simples
    3.2 Déclarations des types structurés

 
4. Instructions en Pascal


4.1 Instruction d'affectation
4.2 Instruction de condition
4.3 Instruction d'itération while…do

4.4 Instruction d'itération repeat…until
4.5 Instruction d'itération for…do
4.6 Instruction case…of


5. Fonctions et procédures en Pascal

6. Paramètres en Pascal
6.1 Lecture seulement
6.2 Accès direct

7. Fonction ou procédure ?

8. Visibilités des variables

9. Variables dynamiques ou pointeurs

10. Récursivité en programmation


Il ne s'agit pas d'apprendre systématiquement toutes les subtilités du langage pascal, mais plutôt d'un résumé consistant mais suffisant, visant à se aqcuérir les principes de base du langage relativement à la programmation.
Le lecteur tirerait avantage à récupérer un polycopié en ligne d'un cours de pascal (taper pascal sur un moteur de recherche du web ou bien aller à http://www.developpez.com rubrique pascal-delphi) pour se étudier complètement le langage. La société Borland-Inprise met sur son site web, gratuitement par téléchargement, des compilateurs pascal anciens mais efficaces pour le débutant (http://www.borland.fr).

PanneauPascalAlgo.dif

1. Rappel de la structure d’un programme Pascal

     
    Nous allons utiliser une description d’un Pascal réduit à l’aide des diagrammes syntaxiques.

    Un programme Pascal est composé de la façon suivante :

    - Soit donc d'une partie en-tête ( nom , paramètres ) :
     
    - d'une partie corps (ou Bloc) :

    - et se termine par un point :

    Exemples d'en-tête :
     

    1°) program exemple_01 ( input, output ) ;

    2°) program exemple_02 ;

    Le langage Pascal étant structuré, un bloc est composé de sections ou paragraphes bien séparés :

    - les étiquettes ou label,
    - les constantes ou const,
    - les types ou type,
    - les variables ou var,
    - les fonctions et les procédures,
    - les instructions exécutables.

    Un Bloc Pascal: 


     
    En pratique un bloc Pascal contient deux parties : des déclarations et des instructions 

    Exemple de programme avec Bloc :



    2. Les opérateurs en pascal

    Liste de tous les opérateurs en Pascal.
     

    Ce sont les règles de composition qui précisent la priorité retenue entre les différents opérateurs du langage. Ces priorités sont réparties en 4 niveaux :
     


     

    2.1 Les opérateurs multiplicatifs

       

       
       
      Opérateur  Types des opérandes Type du résultat
      * multiplication real ou integer real ou integer
      * intersection Ens=set of T0 Ens=set of T0
      / division real ou integer real
      div quotient euclidien integer integer
      mod reste euclidien integer integer
      and et logique boolean boolean


    2.2 Les opérateurs additifs
       

       
       
      Opérateur  Types des opérandes Type du résultat
      + addition real ou integer real ou integer
      + union Ens=set of T0 Ens=set of T0
      - soustraction real ou integer real ou integer
      - différence Ens=set of T0 Ens=set of T0
      or ou logique boolean boolean

      ATTENTION :
      Lorsqu'ils sont unaires les opérateurs "+" et "-" indiquent le signe de la variable.

    2.3 Les opérateurs relationnels
       

       
      Opérateur  Types des opérandes Type du résultat
      < inférieur strict type scalaire boolean
      > supérieur strict type scalaire boolean
      <= inférieur ou égal type scalaire boolean
      <= inclusion large Ens=set of T0 boolean
      = égal type scalaire boolean
      = égal type pointeur boolean
      = égal Ens=set of T0 boolean
      >= supérieur ou égal type scalaire boolean
      >= contient large Ens=set of T0 boolean
      <> différent type scalaire boolean
      <> différent type pointeur boolean
      <> différent Ens=set of T0 boolean
      in appartient Ens=set of T0 boolean
      in appartient type intervalle boolean


    Liste de tous les opérateurs selon le type de données en Pascal :

opérateurs sur les entiers


 opérateurs sur les réels

opérateurs sur les ensembles : set of


opérateurs sur les booléens

opérateurs de comparaison sur un type T


    2.4 Déclarations des constantes

    Sert à associer un identificateur à une valeur de constante, non modifiable dans le reste du programme.

     

    Exemple :

    program exemple_03 ;
    const
        x=12; <------------ constante de type integer.
        a2=true; <------------ constante de type boolean.
        y='h'; <------------ constante de type char.
        r2=25.36; <------------ constante de type real.
    .
    .
    .
    Il existe 3 identificateurs de constantes prédéfinis : True , False , et Nil .
     
     
     

    3. Déclarations des types en Pascal
     

    Les types sont utilisés pour créer de nouveaux domaines de définition de variables. Une déclaration d'un nouveau type de données sert associer un identificateur à un type de données, construit par l'utilisateur. Cette construction élaborée à l'aide de constructeur de type détermine l'ensemble des valeurs possibles des variables de ce nouveau type.

    On classe les types en 3 catégories :

    Type

         < déclaration  de type >
 

     
     

    3.1 Déclarations des types simples

    Cette déclaration est composée des :
     


    A) Type simple :

                 < Type simple >
 

     

    B) Types simples / Les types scalaires ( 2 sortes ) :

    Les types prédéfinis :


    Les types énumérés :

    identif0 = ( identif1,identif2,....,identifk )
     

    Il s'agit ici d'une définition en extension des éléments du type. Les identifn sont des constantes symboliques du type et doivent être tous différents dans la même énumération, et ne peuvent se retrouver ni dans une autre énumération, ni redéfinis ailleurs.
     
    Ce type est doté d'une fonction spécifique : ord qui dénote le numéro d'ordre d'un élément dans l'ensemble des valeurs du type (attention l'ordre est construit de gauche à droite et la numérotation débute à la valeur 0).

    Exemple :

    Type
        jour = (lundi, mardi, mercredi, jeudi, vendredi, samedi, dimanche ) ;
     
    lundi mardi mercredi jeudi vendredi samedi dimanche 
          0      1       2     3      4      5      6

    Ainsi :

    ord(jeudi) = 3
    ord( lundi) = 0
     

    REMARQUE :
    Les types scalaires sauf le type real bénéficient de 2 fonctions succ et pred

    succ : T -----> T / succ (ai) = ai+1 (successeur dans T , lorsqu'il existe)

    pred : T -----> T / pred (ai) = ai-1 (prédécesseur dans T, lorsqu'il existe )
     


     

    C) Types simples / Les types intervalles :

     
     

    Il peut être défini comme un intervalle fermé borné d'un autre type scalaire, sauf real.
     

    Exemples :

    Type
        jour = (lundi , mardi , mercredi , jeudi , vendredi , samedi , dimanche ) ;
        mois = 1..12 ;
        week_end = vendredi..dimanche ;
        lettre_min = 'a'..'z' ;
        lettre_maj = 'A'..'Z' ;
     
     

    3.2 Déclarations des types structurés

       
      Type structuré / Tableau
      Accès aux variables d'un type tableau
      Type structuré / Ensemble
      Type structuré / Enregistrement
      Type structuré / Enregistrement/partie fixe
      Enregistrement/accès aux champs


 
Une définition de type structuré, précise par l'intermédiaire du constructeur de type, la méthode de structuration et le type de ses composants.
 

Type structuré / Tableau :

 
 

Le type tableau est défini par le constructeur de type array[ ] of. C'est une structure homogène, formée d'un nombre fixe de composants qui sont tous du même type de base. Tous les composants d'un tableau sont désignés par des indices, qui sont des expressions appartenant au type indice du tableau.
 
Un tableau est en fait une structure de donnée à accès aléatoire , c'est à dire que tous ses composants peuvent être sélectionnés et atteints de manière égale. Ils sont rangés dans l'ordre des indices.

Un tableau à n dimensions (un vecteur est représenté par un tableau à une dimension, une matrice par un tableau à deux dimensions...) est défini par n types d'indices séparés par des virgules.
 
Un type indice est un type simple sauf real et integer.

Exemple :

Type
    jour = (lundi, mardi, mercredi, jeudi, vendredi, samedi, dimanche ) ;
    mois = 1..12 ;
    week_end = vendredi..dimanche ;
    lettre_min = 'a'..'z' ;
    lettre_maj = 'A'..'Z' ;
    tableau_01 = array[jour] of mois;
    tableau_02 = array[jour] of array[1..30] of mois;
    tableau_03 = array[jour,1..30] of mois;
    tableau_04 = array[lettr_min,0..5,jour,boolean] of char;
var
    T1 : tableau_01;
    T2 : tableau_02;
    T3 : tableau_03;
    T4 : tableau_04;
    etc.....
 

ATTENTION:
Notons ici que malgré la similitude de construction des deux types tableau_02 et tableau_03 (ce sont des types de matrices où l'indice ligne varie dans le type jour, et l'indice colonne varie dans le type 1..30), ce ne sont pas des types identiques, car ils sont déclarés séparément.

Donc dans l'exemple précédent, T2 et T3 ne sont pas des tableaux du même type.


 

Accès aux variables d'un type tableau

Il faut, afin de pouvoir accéder à un composant d'un tableau, utiliser des indices obligatoirement de même type et en même nombre qu'indiqués dans la déclaration.
 

Exemple : (en reprenant les déclarations précédentes)

var
    T1 : tableau_01;
    T2 : tableau_02;
    T3 : tableau_03;
    T4 : tableau_04;
    m : mois;
    j : jour;
    k : 1..30;
    L,b: boolean;
    n : integer;
    c : lettre_min;

Les écritures suivantes sont licites :

j:= jeudi; k:= 20; c:='f'; L:=false; b:=true; n:=2;
T1[mardi]:= 8; T1[j]:= 10;
T2[mardi,5]:= 8; T2[mardi] [5]:= 8; T2[j,k-3]:= 8; T2[j] [k-3]:= 8;
T3[mardi,5]:= 8; T3[mardi] [5]:= 8; T3[j,k]:= 8; T3[j] [k]:= 8;
T4['t',3,samedi,true]:= 'h'; T4['t'][3][samedi][true]:= 'h';
T4[c,n+2,j,L or b]:= '+'; ...... etc
 
 

Type structuré / Ensemble :


Un type ensemble est défini d'un manière extensive par le constructeur set of, le domaine des valeurs de ses éléments par son type de base.
 
le type composant est un type simple sauf real et integer.

C'est un ensemble fini et l'on peut construire tous ses sous-ensembles :

Exemple :

Type
    couleur = (noir,blanc);
    ens_couleur = set of couleur;
var
    x,y,z,t : ens_couleur;
begin
    x := [ ] ; <--- ensemble vide (0 élément)
    y := [noir]; <--- ensemble (1 élément)
    z := [blanc]; <--- ensemble (1 élément)
    t := [noir,blanc]; <--- ensemble (2 éléments : maximum possible de l'exemple)
etc.....

On peut dire en fait que le type ens_couleur est l'ensemble P(couleur) (ensemble des parties) et que toute variable du type ens_couleur est un sous-ensemble de P(couleur).
 
 

Type structuré / Enregistrement :

 
 

Le type enregistrement est une collection de composants appelés champs de l'enregistrement. Ils peuvent être d'un type quelconque sauf le type fichier. C'est une structure hétérogène.
 
Tous les identificateurs de champs d'une même structure enregistrement doivent être différents à l'intérieur de l'enregistrement. Ils permettent d'accéder directement aux éléments de l'enregistrement.

 

Type structuré / Enregistrement/partie fixe :


Exemple:

Type
    enregis = record
        jour : (lundi,mardi,dimanche);
        x,y : integer;
        mois : 1..12;
        T_paie : array[boolean,1..30] of real;
    end;
 
 

Enregistrement/accès aux champs :


 
 
L'accès aux champs à l'intérieur d'un enregistrement s'effectue à l'aide de l'identificateur de l'enregistrement (identif de record), puis de celui du champs (identif de champs) auquel on désire accéder, dans cet ordre, comme en désignant un chemin accédant aux éléments en écrivant de gauche à droite.

Exemple :

Type
    Tenregis = record
        jour : (lundi,mardi,dimanche);
        x,y : integer;
        mois : 1..12;
        T_paie : array[boolean,1..31] of real;
    end;

var
    A : Tenregis;

begin
    A.jour:=;mardi;
    A.mois:=8;
    A.y:=125;
    A.x:=0;
    A.T_paie[false,A.mois] := -2.37
etc.....
 


4. Instructions en Pascal

Ce sont les  traductions des instructions algorithmiques de notre langage de description formelle d'algorithme que nous avons dénommé LDFA.

LDFA Pascal
W (instruction vide) pas de traduction
debut i1 ; i2; i3; ...... ; ik fin  begin i1 ; i2; i3; ...... ; ik end
x ¬ a  x := a
;  (ordre d'exécution) ;
Si P alors E1 sinon E2 Fsi  if P then E1 else E2
( attention défaut, pas de fermeture !)
Tantque P faire E Ftant while P do E
( attention, pas de fermeture)
répeter E jusquà P repeat E until P
lire (x1,x2,x3......,xn ) read(fichier,x1,x2,x3......,xn )
readln(x1,x2,x3......,xn )
Get(fichier)
ecrire (x1,x2,x3......,xn )  write(fichier,x1,x2,x3......,xn )
writeln(x1,x2,x3......,xn )
Put(fichier)
pour x<-a jusquà b faire E Fpour for x:=a to b do E (croissant)

for x:=a downto b do E (décroissant)
( attention, pas de fermeture)

SortirSi  P if P then Break


4.1 Instruction d'affectation

L'affectation est applicable à tous les genres de variables du pascal sauf au type file of.

 

 Sémantique:

 Exemple :

program Affectation ;
type
    Temperature = -20 .. 40 ;
    LettreMin = ' a ' .. ' z ' ;
    Jour = ( lundi , mardi , mercredi , jeudi ) ;
var
     a : integer ;  b : char ; 
     c : string ;
     Temp : Temperature ; Lmin :  LettreMin ;
     Day : Jour ;
begin
    Temp := 18 ;

     a := (2+Temp)*4 ;
     b := 'F' ;
     c := 'bon'+'jour' ;
     Lmin := 'f' ;
     Day := mercredi ;
 end.
  // Après affectations :    
 
// Temp vaut 18
// a vaut 80
// b vaut 'F'
// c vaut 'bonjour'
// Lmin vaut 'f'
// Day vaut mercredi

 

4.2 Instruction de condition

Dans l'instruction if, l'expression est un prédicat ( expression contenant des variables, prenant la valeur vrai ou faux), les blocs <instruction> représentent soit une instruction simple, soit une instruction composée (begin ..... end).

Sémantique:

 cas du if...then

 
cas du if...then...else

 Exemple :

program Condition ; 
var
     x, y ,z : integer ; 
begin
    x := 10 ;

    y := x*4 ;
    if y>100 then z := y
    else z := 0;
    if z = 0 then
        y := 0
    x := 0 ;
 end.
 // Exécution pas à pas :
// x vaut 10
// y vaut 40
// y>100 est false
  donc z vaut 0

// z=100 est true
   donc y vaut 0
// x vaut 0
(à la fin : x=0, y=0, z=0)

 

4.3 Instruction d'itération while…do

 

 
Dans l'instruction while…do, l'expression est un prédicat ( expression contenant des variables, prenant la valeur vrai ou faux), le blocs <instruction> représente soit une instruction simple, soit une instruction composée (begin ..... end).
 

Sémantique:

C'est une instruction de boucle.

C'est une boucle non finie (c-à-dire que l'on ne peut pas connaître dans les cas de figure si une boucle quelconque de ce type s'arrêtera après un nombre fini d'exécution).

 
Exemple :

program WhileDo ; 
var
     x, y  : integer ; 
 begin
    x := 1 ;
    y := 0 ;
    while x<4 do
    begin
       x := x+1 ;
       y := y +x
    end;
    writeln ('x=', x , 'y=', y)
end.
 
Le programme écrit :
x=4 y=9
  Exécution pas à pas :
x vaut 1
y vaut 0
x<4 est true
  donc x vaut x+1 soit 2

  et y vaut y+x soit 2
x<4 est true
  donc x vaut x+1 soit 3

  et y vaut y+x soit 5
x<4 est true
  donc x vaut x+1 soit 4

  et y vaut y+x soit 9
x<4 est false  donc arrêt
(à la fin : x=4, y=9)

 

 4.4 Instruction d'itération repeat…until

 


Dans l'instruction repeat…until, l'expression est un prédicat ( expression contenant des variables, prenant la valeur vrai ou faux), le blocs <instruction> représente soit une suite d'instructions simples.

 

Sémantique:

C'est une instruction de boucle.

C'est une boucle non finie (c-à-dire que l'on ne peut pas connaître dans les cas de figure si une boucle quelconque de ce type s'arrêtera après un nombre fini d'exécution).

La différence avec le while .. do réside dans le fait que le repeat ... until exécute toujours au moins une fois le bloc d'instructions avant d'évaluer l'expression booléenne alors que le while ... do évalue immédiatement son expression booléenne avant d'exécuter le bloc d'instructions.

 Exemple :

program RepeatUntil ; 
var
     x, y  : integer ; 
 begin
    x := 1 ;
    y := 0 ;
    repeat
       x := x+1 ;
       y := y +x
    until x>=4;
    writeln ('x=', x , 'y=', y)
end.
 
Le programme écrit :
x=4 y=9
 // Exécution pas à pas :
// x vaut 1
// y vaut 0
// on entre dans le repeat
  donc x vaut x+1 soit 2

 //  et y vaut y+x soit 2
// x>=4 est false
  donc x vaut x+1 soit 3

 //  et y vaut y+x soit 5
// x>=4 est false
  donc x vaut x+1 soit 4

  et y vaut y+x soit 9
// x>=4 est true donc arrêt
(à la fin : x=4, y=9)

Ce programme fournit le même résultat que celui de la boucle while…do, car il y a une correspondance sémantique entre ces deux boucles :

repeat <instruction> until <expr>

<instruction> ;

while not<expr>  do    <instruction>

 


4.5 Instruction d'itération for…do

C'est une instruction de boucle, il y a deux genres d'instructions for (for...to et for...downto)

 

Version for <identificateur> := <Expr1>to  <Expr2> do <Instruction> :



Version for <identificateur> := <Expr1> downto  <Expr2> do <Instruction> :

 Sémantique:

L'indice de boucle prend toutes les valeurs (par ordre croissant ou décroissant selon le genre de for) comprises entre <Expr1> et <Expr2> bornes inclues.

Tant que la valeur de l'indice de boucle ne dépasse pas

la valeur de <Expr2>, le bloc d'instruction est réexécuté

C'est une boucle finie (c-à-dire que l'on connaît à l'avance le nombre de tours de boucle).

Exemple :

program ForDo ; 
var    x, y  : integer ; 

begin
  y :=0 ;  

  for x := 1 to 3 do
             y := y +x
    end.
Exécution de chaque tour de boucle :
          y vaut 0
x vaut 1 =>   y vaut 0+1=1
x vaut 2 =>   y vaut 1+2=3
x vaut 3 =>   y vaut 3+3=6

x vaut 4 =>   arrêt
(à la fin : x=4, y=6)

 

4.6 Instruction case…of

C'est une instruction de choix :

 <expression> doit être de l'un des types :  integer, char, boolean, énuméré, intervalle .
<constante> doit obligatoirement être du même type que <expression>

<Instruction> est un bloc d'instruction simple ou composée (begin ..... end).

Sémantique:

C'est une instruction structurée équivalente à une série de if...then...else imbriqués. Cette instruction lorsque cela est possible, doit être préférée à un emboîtement de if...then...else dont la lisibilité n'est en fait pas optimale.

if...then...else imbriqués

case ... of équivalent

 if x = 3 then E1 else
  if x = 4 then E2 else
    if x = 5 then E2 else
     if x = 6 then E2 else
       if x = -5 then E3 else Ef
  case x of
     3     : E1 ;
     4..6 : E2 ;
     -5   : E3 ;

     else Ef
  end

 Exemple :

program CaseOf ; 
var    x, y  : integer ; 

begin
  y :=1 ;
  for x := 0 to 4 do
          case x+1 of
             0..3 : y :=y*2 ;
             4 : y := y+100
             else y:=0 ;
          end
    end.
 
         
          y vaut 1
 
Exécution du case dans la boucle :
x vaut 0 => x+1 vaut 1 (dans 0..3) =>   y vaut 1*2=2
x vaut 1 => x+1 vaut 2 (dans 0..3) =>   y vaut 2*2=4
x vaut 2 => x+1 vaut 3 (
dans 0..3) =>   y vaut 4*2=8
x vaut 3 => x+1 vaut 4          =>   y vaut 8+100=108
x vaut 4 => x+1 vaut 5 (else) =>   y vaut 0
x vaut 5 =>   arrêt
 
( à la fin : x=4, y=0 )

 

5. Fonctions et procédures en Pascal

Le langage Pascal a été conçu à l'origine comme  un langage pédagogique d'implantation de la programmation de type algorithmique; grâce à son extension objet Delphi il est utilisé comme outil de développement professionnel en entreprise.

La programmation algorithmique est une programmation hiérarchisée descendante

Cette décomposition descendante hiérarchique est construite à l'aide de blocs de programme notés aussi des sous-programmes.

Un bloc comporte donc des données locales, du code (instructions ou corps du bloc), des données d'entrée et/ou des données de sortie (permettant les échanges d'informations entre les différents blocs de la hiérarchie) :

L'exemple ci-après représente trois blocs B1, B2 et B3 échangeant des informations (en fait chacun calcule la somme des deux entiers qu'il reçoit en entrée et renvoie leur somme : 

 

Le bloc B1 reçoit en entrée 12 et 15 et renvoie la somme 12+15 = 27 vers le bloc B2, la valeur 27 devient une donnée d'entrée pour le bloc B2 qui reçoit comme autre entrée la valeur 10. Le bloc B2 renvoie vers le bloc B3 le résultat 27+10 = 37 etc... 

Nous remarquons que chaque bloc est indépendant des autres blocs. La seule liaison qui intervienne ici se situe dans le passage des données d'un bloc vers un autre bloc. Le code et les données locales d'un bloc fixé sont inaccessibles aux autres blocs. 

En pascal les blocs sont implémentés soit par des fonctions  : 

 En pascal les blocs sont implémentés aussi par des procédures  : 

 Voici la syntaxe de déclaration des procédures en Pascal :

 
Voici la syntaxe de déclaration des fonctions en Pascal :

 Exemples de déclarations avec et sans paramètres formels :

procedure Somme (x,y :integer; var z :integer) ; 
begin
  z := x +y
end ;
function Somme (x,y :integer): integer ; 
begin
  result := x +y
end ;
procedure Somme  ; 
   var    x, y  : integer ; 

begin
  y :=1 ; x := 2;
       writeln( x+y)
end ;
function Somme : integer ; 
   var    x, y  : integer ; 
begin
y :=1 ; x := 2; 
result := x +y
end ;

 

6. Paramètres en Pascal


On s’intéresse dans ce paragraphe aux rapports qu’il y a entre un programme appelant et un sous-programme appelé uniquement en Pascal.

 Soit par exemple une procédure B ayant 3 paramètres formels et renvoyant dans le troisième paramètre la somme des deux premiers : 

 

Les paramètres formels d'une procédure jouent le rôle de variables muettes et servent à décrire le fonctionnement d'une procédure. Ils ont la même utilisation qu'une variable dans un polynôme mathématique. Les deux écritures P(x) = 3x2 - 4x + 5 et P(t) = 3t2 - 4t + 5 représentent mathématiquement le même polynôme, il en est de même pour une procédure.

On peut changer tous les paramètres formels d'une procédure sans en changer son fonctionnement.

Les deux déclarations ci-dessous sont identiques :

procedure B (x , y :integer; var t :integer) ; 
begin
  t := x +y
end ;
 
procedure B (a , b integer; var c :integer) ; 
begin
  c := a +b
end ;

L'intérêt pratique d'une procédure et en général d'un sous-programme est essentiellement de pouvoir exécuter toujours la même action mais avec des valeurs différentes.

Par exemple une procédure P qui utilise une autre procédure B qui effectue la somme de deux entiers. La procédure B fonctionne comme une sorte de boîte noire qui reçoit deux valeurs en entrée et qui retourne leur somme comme dans le pseudo-code ci-dessous :

Lignes fictives de code de la procédure P utilisant la boîte noire (procédure B)

La boîte "faire la somme" est utilisée une première fois pour sommer 5 et 8, puis plus loin elle est utilisée une deuxième fois pour sommer -2 et 105.

Le mécanisme qui permet d'utiliser la procédure B dans le code de la procédure P se dénomme l'appel de procédure. P se dénomme la procédure appelante.

Reprenons l'exemple du polynôme écritures P(x) = 3x2 - 4x + 5 , nous savons qu'en donnant une valeur effective à la variable x (par exemple x = 2) on obtient un résultat noté P(2) qui vaut:  P(x) = 3.22  - 4.2  + 5 = 9.

L'appel de procédure est un procédé très semblable au calcul du polynôme sur une valeur. La procédure a besoin qu'on lui fournisse des variables contenant effectivement des valeurs. De telles variables se dénomment les paramètres effectifs de la procédure.

Précisons un peu plus l'utilisation d'une procédure S avec des variables. Supposons que S serve à calculer la somme de deux valeurs 5 et 8 contenues respectivement dans deux variables locales a et b d'une autre procédure nommée P dont le seul paramètre x renvoie le résultat 13 du calcul obtenu par appel de la procédure B dans le code de la procédure P :

L'appel S(a,b,x) s'effectue sur des paramètres effectifs qui sont nécessairement des variables existantes, soit déclarées dans un paragraphe var dans la zone des données locales, soit déclarées en tant que paramètres de la procédure appelante.

L'appel se fait avec un nombre de paramètres effectifs ègal à celui des paramètres formels en respectant l'ordre et la cohérence des types. On peut imaginer que lors d'un appel à la procédure S par le code de la procédure S, le code de la procédure S vient s'imbriquer fictivement dans le code de P à l'endroit de l'appel avec comme variables les paramètres effectifs :

 
Comment a lieu cet appel, cette inclusion fictive du code ?

 

On dénomme l'action qui consiste à appeler sur des paramètres effectifs, le passage des paramètres effectifs  ou encore la transmission des paramètres effectifs.

 

Il faut savoir qu’un paramètre effectif transmis au sous-programme appelé est un moyen d’utiliser ou d’accéder à une information appartenant au bloc appelant (le bloc appelé peut être le même que le bloc appelant, il s’agit alors de récursivité).

 

 
Pascal ne dispose que de 2 modes de passage sur les 5 modes généraux :

  • Le passage par valeur,
  • le passage par référence ou adresse.

 

6.1 Lecture seulement : passage par valeur

Dans un passage par valeur, le paramètre formel est considéré comme une variable locale dans le corps du sous-programme. Sa valeur est initialisée au début de chaque exécution du sous-programme avec la valeur du paramètre effectif correspondant.

Il y a recopie de la valeur du paramètre effectif dans une zone spécifique locale à la procédure. Toutes les opérations qui sont effectuées sur le paramètre formel n’affectent que cette valeur locale.

Ecriture en Pascal procedure sp(... x: real ....)

passage par valeur


6.2 Accès direct : passage par adresse ou par référence

Dans un passage par adresse le paramètre formel est traité comme une variable dont l’adresse qui est transmise au moment de chaque appel, est celle du paramètre effectif correspondant. L’adresse de la variable effective autorise toutes les modifications immédiatement sur cette variable quelle que soit sa localisation.
 

Ecriture en Pascal procedure sp (....var x : real .....)


    passage par référence

Comparaison des avantages et des inconvénients des 2 modes

 Passage par valeur :

  • Avantage : sécurité et protection des informations.
  • Inconvénient : lenteur due à la recopie des données et doublement de la place mémoire occupée (mais convient bien pour des variables simples !).

 
Passage par référence :

  • Avantage : rapidité d’accès aux données, moindre occupation mémoire puisqu’il ne s’agit que d’une adresse.
  • Inconvénient : ce mode est dangereux à cause de la non protection des données et de la nécessité qu’il y a de connaître la façon dont sont implantées physiquement les données sur la machine.

Ces deux modes de passage des paramètres sont présents dans des langages comme C++, java, Ada, Visual-Basic .net,  Delphi et C#. Ils suffit donc pour le débutant, de bien comprendre le processus avec le pascal et par analogie il pourra l'utiliser avec les autres langages.

Exemple :

procedure B1 (x : integer; var y : integer) ; 
begin
  y := 10*x
end ;

 
Dans la procédure B1
     x est passé par valeur