Tutto è partito da qui:

click
Allora provo a rimediare.
Il Fortran è stato il primo linguaggio di programmazione “umano”. Prima c’era solo l’assembler –si dovrebbe dire assembly.
Come linguaggio non era malaccio –buona la prima, si direbbe nel cinema– e si è espanso e imposto tanto che quando ho cominciato io sui computer normali c’era solo quel compilatore. O volete prendere in considerazione i gestionali che usavano il Cobol? dai siamo seri 8)
Uno dei vantaggi del Fortran è che il programma può essere suddiviso in parti e queste ultime possono essere scritte e compilate separatamente. E si mettono insieme solo al momento del linkaggio, per produrre l’eseguibile.
Quindi c’è un main (non ricordo se allora si chiamasse così) e tante altre procedure, pezzi. Si chiamano subroutine. A dire il vero c’è anche un altro tipo di procedura, la funzione, ma per ragioni che non ho mai capito i Veri Programmatori Fortran preferivano la subroutine.
Io che sono un cerchiobottista (in questo campo) vedrò di illustrarle entrambe. E proporrò una versione in C, per illustrare una grossa differenza tra i due approcci.
Non è una guida o un corso, mi limito a rispondere a un quesito, intesi nèh 8)
c1234567
program demo
i = 1
j = 10
r = 3.14
write(*,*) "main - prima", i, j, r
call duplica(i, j, r)
write(*,*) "main - dopo ", i, j, r
end
**********************************************
subroutine duplica(ip, jp, rp)
write(*,*) 'duplica - prima', ip, jp, rp
ip = ip * 2
jp = jp * 2
rp = rp * 2
write(*,*) 'duplica - dopo ', ip, jp, rp
end
Chiaro vero? OK! In Fortran non è che si può scrivere come ti pare e piace (n.b.: adesso sì, si chiama free format ma è una cosa nuova, del 1995) ci sono un paio di regole:
- un C o un * in colonna 1 indica che la riga è un commento;
- nelle colonne 1-5 puoi mettere una label numerica (numeri da 1 a 99999); i numeri, arbitrari, servono per i cicli, i goto (e altri salti) e altro ancora;
- il codice è tra le colonne 7 e 72, comprese, il resto viene ignorato;
- la colonna 6 è riservata alla continuazione di un’istruzione troppo lunga; per dire che la riga è una continuazione della precedente bisogna mettere qualsiasi carattere tranne il blank e lo zero.
write(*,*) seguito da variabili significa scrivi sullo standard output (primo *) nel formato di default (secondo *).
La chiamata alla subroutine si fa con call <nome della subroutine> seguita dai parametri che si vogliono passare.
La subroutine stessa è esattamente come il main ad eccezione dell’intestazione: subroutine <nome della subroutine>.
Nelle versioni dal 77 in poi le stringhe possono essere delimitate sia da apici semplici che doppi. Prima non c’erano. Ma ogni variabile poteva essere vista come caratteri e quindi era come se ci fossero, discorso lungo…
In genere non si definisce il tipo delle variabili, se si usa la regola predefinita: sono tutte float (in gergo real*4) tranne quelle il cui nome inizia con una lettera compresa tra I e N (come INteger).
Proviamo a compilare e eseguire

Chiaro no? Sì, capita una cosa strana, difforme dal C 8)
Per chi ancora non l’ha vista ecco il codice C equivalente
#include <stdio.h>
void duplica(int ip, int jp, float rp);
void main() {
int i = 1, j = 10;
float r = 3.14;
printf("main - prima %d %d %f\n", i, j, r);
duplica(i, j, r);
printf("main - dopo %d %d %f\n\n", i, j, r);
}
void duplica(int ip, int jp, float rp) {
printf("duplica - prima %d %d %f\n", ip, jp, rp);
ip *= 2;
jp *= 2;
rp *= 2;
printf("duplica - dopo %d %d %f\n", ip, jp, rp);
}
compilando ed eseguendo si ha

Trovato? Troppo facile, vero? In Fortran tutti i dati vengono passati per riferimento, nel C (e credo dappertutto) per valore. OK! discorso lungo, non è questa la sede, dai! 8)
Si era parlato anche di funzioni, ecco un esempio
c1234567
program demo
common /mieidati/ ivar, fvar
ivar = 100
fvar = 2.7818
write(*,*) "main - prima ", ivar, fvar, k
k = myfunc(8)
write(*,*) "main - dopo ", ivar, fvar, k
end
**********************************************
function myfunc(n)
common /mieidati/ i, f
write(*,*) 'in myfunc - prima', n, i, f
i = i + n
f = f + n
write(*,*) 'in myfunc - dopo ', n, i, f
myfunc = n * n
end
La chiamata alla funzione è quella usuale, la definizione è: function <nome della funzione>. Notare la sintassi per il valore ritornato, diversa da quella cui siamo abituati. In fortran esiste return ma non è lo stesso del C: abbandona immediatamente la procedura corrente.
Nell’esempio c’è ancora una cosa da notare: il common. Il common, croce e delizia del Fortran, permette di gestire le variabili che conservano il loro valore attraverso le varie procedure. Perché la cosa sia flessibile (ricordare che possiamo compilare separatamente i vari file componenti il programma) non conta il nome della variabile ma la sua posizione. Nel caso in oggetto nel main i primi 4 byte del common sono occupati dalla variabile ivar nel main e i nella funzione. Chiaro? Fate attenzione che parecchi casini verranno da questo punto, avvisati, nèh!
Compiliamo ed eseguiamo

Notare che non avendo assegnato alcun valore alla variabile k abbia un valore casuale nella prima write.
In C abbiamo
#include <stdio.h>
int myfunc(int n);
float f;
void main() {
int k;
f = 2.7818;
printf("main prima %d %f\n", k, f);
k = myfunc(8);
printf("main dopo %d %f\n", k, f);
}
int myfunc(int n) {
printf("in myfunc %d %f\n", n, f);
f = f + n;
return n * n;
}
che ci da

In questo caso l’equivalente del common è di definire le variabili globalmente. Sì, lo so, lo so! questo è solo un approccio elementare.
A questo punto entrerebbero in scena puntatori, indirizzi e quant’altro. Ma no, mi fermo qui: credo di aver risposto alla domanda di Alessio e Francesco –sempre che qualcuno mi abbia seguito fin qui 8)

Questo post fa parte di una nuova categoria “La Pagina della Sfinge“, mica si riesce sempre a scrivere cose sensate ma superseriose 😉 e notare che ho l’approvazione del dr.prof., qui 8)