La communication entre unités de programmes (programme principal,sous-programmes, fonctions) peut se faire de deux manières très différentes : par passage de paramètres ou par partage d'une zone commune.
Exemple (trivial) :
PROGRAM PP
INTEGER A,B,C,D
READ (*,*) A,B
CALL SP(A,B,C)
CALL SP(1,2,D)
WRITE (*,*) A,B,C,D
STOP
END
SUBROUTINE SP(X,Y,Z)
INTEGER X,Y,Z
Z = X + Y
RETURN
END
On parle de paramètres formels quand on se place du coté de l'unité de programme appellée (X,Y et Z sont les paramètres formels de SP), et de paramètres effectifs d'un appel (A,B,C paramètres effectifs du premier appel à SP dans PP, 1,2,D paramètres effectifs du second).
La première chose à savoir est que les paramètres sont toujours passés par adresse. Ainsi, il est possible de modifier - depuis l'intérieur d'un sous-programme - le contenu d'une variable reçue comme paramètre (dans notre exemple, il est clair que le sous-programme SP modifie son troisième argument). Les résultats d'expressions arithmétiques (et les constantes) utilisés comme paramètres effectifs sont traités de la même manière : dans l'appel CALL SP(A+B,0,C) le premier paramètre effectif sera en fait une variable intermédiaire contenant le résultat de l'addition de A et B, le second paramètre une zone mémoire contenant la valeur 0.
La seconde chose -très importante- à savoir est que la correspondance de types entre arguments effectifs et arguments formels n'est pas vérifiée par le compilateur FORTRAN. Ainsi l'appel CALL SP (1.0,1.0,C) conduira-t-il à un résultat douteux. Il n'y a pas non plus de contrôle du nombre de paramètres. Ces vérifications sont laissées à la charge du programmeur. Rappelons en particulier que les constantes entières entre -32768 et 32767 sont de type INTEGER, et que les constantes plus grandes sont en INTEGER*4.
Exemple :
REAL FUNCTION DERIV(F,X)
C
C Calcule la valeur de la dérivée de la fonction F en X
C
REAL F,X
DERIV = ( F(X+0.01) - F(X-0.01) ) / 0.02
RETURN
END
REAL FUNCTION TEST (X)
C
C Un exemple de fonction à une variable réelle
C
TEST = X**2 + SIN(X)
RETURN
END
PROGRAM ESSAI
EXTERNAL TEST
REAL TEST,POINT
READ (*,*) POINT
WRITE (*,*) 'Au point ',POINT,
S 'la derivee vaut',DERIV(TEST,POINT)
STOP
END
La déclaration EXTERNAL TEST (du programme principal) signale au compilateur FORTRAN que le nom TEST désigne une unité de programme (et non pas une variable).
Dans DERIV, il est «conseillé» de déclarer le type du paramètre formel F. Le compilateur arrive à déterminer que F est une FUNCTION, car le nom F est suivi de parenthèses, et aucun tableau F n'est déclaré.
Si, dans le programme principal, on avait voulu passer en paramètre une fonction prédéfinie (par exemple SIN), alors on doit utiliser l'instruction INTRINSIC SIN (au lieu d'EXTERNAL).
Exemple :
REAL FUNCTION SOMME(T,N)
INTEGER N
REAL T(N)
C
C Calcul de la somme des N elements du tableau T
C
INTEGER I
REAL S
C
S = 0.0
DO 100,I=1,N
S = S + T(I)
100 CONTINUE
SOMME = S
RETURN
END
Dans cet exemple le tableau (formel) T possède une dimension (formelle) donnée par le paramètre (formel) N. C'est le seul cas de taille formelle possible, car T n'est qu'une référence à un objet existant par ailleurs (dans l'unité appelante), et la déclaration de T ne fait aucune réservation de place mémoire.
Exemple :
PROGRAM TRUC
REAL X,Y
READ (*,*) X,Y,F
Y = F(X,*99)
WRITE (*,*) 'Resultat =',Y
STOP
C
C En cas d'erreur ................................
99 WRITE (*,*) 'F n''est pas definie en ',X
STOP
END
REAL FUNCTION F ( X , * )
REAL X,DENOM
DENOM = X - 1.0
IF (DENOM .EQ. 0.0) RETURN 1
F = SIN(X) / DENOM
RETURN
END
Ici le second paramètre de la fonction F est une adresse de retour alternative. Si l'instruction «RETURN 1» est exécutée dans F, alors un branchement est effectué à l'instruction 99 du programme principal. On peut avoir plusieurs adresses de retour alternatives, c'est la valeur de l'expression située derrière le RETURN qui détermine le numéro de l'adresse choisie.
Dans l'unité appelante, n'oubliez pas de mettre une étoile devant les étiquettes que vous passez en paramètres...
Cette facilité est utilisée très souvent pour indiquer (comme ici) l'adresse d'une instruction à exécuter en cas d'anomalie. Elle est finalement très voisine de la forme «READ(....END=...ERR=...)».