Quando è possibile è meglio comunque usare variabili ALLOCATABLE, su cui il compilatore è in grado effettuare un maggior numero di ottimizzazioni.
|
È da notare che i puntatori in F90 hanno, volutamente, delle
funzionalità molto ristrette rispetto ai puntatori in C, in
particolare non è possibile ottenere il valore numerico (indirizzo in
memoria) del puntatore, eseguire su di esso operazioni aritmetiche, e,
nelle espressioni, le variabili di attributo POINTER sono
trattate come variabili ordinarie, cioè rappresentano il valore a cui
il puntatore punta e non il valore del puntatore stesso come accade
invece in C.
|
PROGRAM pointer_cf INTEGER :: a = 5 INTEGER, POINTER :: pa pa => a PRINT*,a ! stampo a: 5 PRINT*,pa ! stampo pa: sempre 5!! pa = pa + 3 END PROGRAM pointer_cf |
#include <stdio.h>
void main(void) {
int a = 5;
int *pa;
pa = &a;
printf("%d\n", a); /* stampo a: 5 */
printf("%d\n", *pa); /* stampo *pa: 5 */
*pa = *pa + 3;
}
|
|
L'unico caso in cui una variabile POINTER si comporta da vero
puntatore è il caso in cui un parametro di un sottoprogramma ha
l'attributo POINTER ed esiste un'interfaccia implicita o
esplicita a tale unità di sottoprogramma; in tal caso il
corrispondente parametro nell'unità chiamante dovrà pure avere
l'attributo POINTER e l'unità di programma chiamata è in
grado, oltre che di cambiare il valore della variabile in questione,
anche cambiarne lo stato di associazione, ad esempio allocandola o
deallocandola.
L'analogo in C del parametro di un sottoprogramma con l'attributo POINTER è il passaggio di un puntatore ad un puntatore.
|
SUBROUTINE modif_pointer(p, n) INTEGER, POINTER :: p(:) INTEGER :: n ALLOCATE(p(n)) p = 0 END SUBROUTINE modif_pointer PROGRAM pointer_cf INTEGER, POINTER :: p INTERFACE SUBROUTINE modif_pointer(p, n) INTEGER, POINTER :: p(:) INTEGER :: n END INTERFACE CALL modif_pointer(p, 10) END PROGRAM pointer_cf SUBROUTINE non_va() INTEGER, POINTER :: p CALL modif_pointer(p, 10) END SUBROUTINE non_va SUBROUTINE non_compila_neanche(p) INTEGER :: p(:) INTERFACE SUBROUTINE modif_pointer(p, n) INTEGER, POINTER :: p(:) INTEGER :: n END INTERFACE CALL modif_pointer(p, 20) END SUBROUTINE non_compila_neanche |
#include <malloc.h>
void modif_pointer(int **p, int n) {
int i;
*p = malloc(n*sizeof(int));
for(i=0; i<n; i++) **p = 0;
}
void main(void) {
int *p;
modif_pointer(&p, 10);
}
non_va_1() {
int *p;
modif_pointer(p, 10);
}
|
|
Si fa notare che nella maggior parte dei casi, cioè quando una
subroutine intende semplicemente usare e/o modificare il
valore di una parametro avente eventualmente l'attributo
POINTER e non modificarne lo stato di associazione,
è non solo inutile, ma anche dannoso aggiungere l'attributo
POINTER a tale parametro.
|
MODULE sette_e_quaranta CONTAINS SUBROUTINE usa_pointer(p) INTEGER :: p(:) p = 0 END SUBROUTINE usa_pointer SUBROUTINE funziona_perfettamente_1() INTEGER :: p(10) CALL usa_pointer(p) END SUBROUTINE funziona_perfettamente_1 SUBROUTINE funziona_perfettamente_2() INTEGER, POINTER :: p(:) ALLOCATE(p(37)) CALL usa_pointer(p) END SUBROUTINE funziona_perfettamente_2 END MODULE sette_e_quaranta |