|
Nel caso di routine senza un'interfaccia esplicita, in F90 le modalità
di passaggio degli array a sottoprogrammi sono le stesse del F77, per
cui un array usato come argomento in un sottoprogramma può avere le
sue dimensioni specificate in varie maniere nel sottoprogramma stesso:
Nel caso una subroutine abbia un'interfaccia (implicita o esplicita che sia), essa può far uso di una modalità più potente di passaggio degli array definita assumed-shape array: in questo caso il sottoprogramma definisce solo il numero di dimensioni dell'array con la notazione array(:,:,...) mentre la shape viene ereditata in maniera automatica dal corrispondente array fornito come argomento della chiamata. Questa è la maniera consigliata per passare array in quanto non richiede di fare assunzioni sulla shape dell'array (che può essere ricavata con le apposite funzioni intrinseche e non necessita di essere passata) e gli eventuali controlli runtime delle dimensioni degli array funzionano al 100%. |
MODULE opvett CONTAINS SUBROUTINE op_sum(v, res) REAL, INTENT(IN) :: v(:,:) REAL, INTENT(OUT) :: res PRINT*,'SHAPE:', SHAPE(v) res = SUM(v) END SUBROUTINE op_sum END MODULE opvett PROGRAM vettori USE opvett REAL :: a(12,18), b(18,12), c(12,12) a=1. CALL op_sum(a,s) PRINT*,s END PROGRAM vettori |
|
F90 permette anche la definizione di array locali ad una subroutine di
tipo automatico, si tratta di array locali le cui dimensioni sono
specificate a partire da parametri interi ricevuti dalla subroutine
stessa o dalla shape di array tipo assumed-shape ricevuti pure come
parametri.
La vita degli array di tipo automatico (che non possono per definizione avere l'attributo SAVE) è limitata al tempo di esecuzione del sottoprogramma in cui sono definiti, per cui sono una valida maniera di definire dello "spazio di lavoro" che in F77 doveva essere esplicitamente passato dal programma chiamante. Nel caso di array di lavoro, l'uso di array automatici è preferibile, per motivi di efficienza, rispetto all'allocazione e deallocazione di variabili ALLOCATABLE ad ogni chiamata; d'altra parte, nel caso di array di grandi dimensioni, lo spazio locale (stack) potrebbe non bastare a contenere tali variabili generando errori runtime di difficile intellegibilità. |
MODULE opvett CONTAINS SUBROUTINE op_sum(v, res) REAL, INTENT(IN) :: v(:,:) REAL, INTENT(OUT) :: res REAL :: work(SIZE(v,1),SIZE(v,2)) PRINT*,'SHAPE:', SHAPE(v) work = v work = LOG(work) res = SUM(work) END SUBROUTINE op_sum END MODULE opvett PROGRAM vettori USE opvett REAL :: a(12,18), b(18,12), c(12,12) a=1. CALL op_sum(a,s) PRINT*,s END PROGRAM vettori |