| <<< zur Fortran-Startseite | |
| << Fortran 2003 | Bibliotheken >> |
| < Datentypen | Ein- und Ausgabe > |
Prozedurenzeiger
Einführung
Mit dem 2003er-Standard unterstützt auch Fortran Zeiger auf Prozeduren (procedure pointer, Funktionszeiger). Diese spielen auch eine wichtige interne Rolle bei der Realisierung objektorientierter Mechanismen und beim C-Binding. Schematisch wird ein Prozedurenzeiger so deklariert:
| procedure( [name] ), pointer :: zeigername |
Die Angabe von name ist optional. Wird an dieser Stelle ein Name, z.B. ein Unterprogrammbezeichner angegeben, so bedeutet dies, dass der Prozedurenzeiger mit allen Unterprogrammen, die das gleiche Interface aufweisen, kompatibel ist. Prozedurenzeiger können wie normale Zeiger gehandhabt werden.
Beispiel:
| Fortran 2003-Code |
program bsp
implicit none
procedure(up), pointer :: pptr => null()
pptr => ooops
call pptr
! Ausgabe:
! ooops
contains
subroutine ooops()
write( *, * ) "ooops"
end subroutine ooops
subroutine up()
end subroutine up
end program bsp
|
Prozedurenzeiger mit implizitem Interface
Bei der Deklaration eines Prozedurenzeigers muss keine explizite Schnittstelle angegeben werden. Im Folgenden wird dies am Beispiel eines mit pptr2 benannten Prozedurenzeigers demonstriert.
Beispiel:
| Fortran 2003-Code |
program bsp
implicit none
procedure( up ) , pointer :: pptr1 => null()
procedure( ) , pointer :: pptr2 => null()
procedure( add ), pointer :: pptr3 => null()
pptr1 => ooops
pptr2 => ooops
call pptr1
call pptr2
! Ausgabe:
! ooops
! ooops
pptr3 => add
write( *, * ) pptr3( 5 , 12 )
! Ausgabe:
! 17
! Folgende auskommentierte Zuordnung waere nicht erlaubt:
! pptr1 => add
contains
subroutine up()
end subroutine up
subroutine ooops()
write( *, * ) "ooops"
end subroutine ooops
function add( a, b )
integer :: add
integer, intent( in ) :: a, b
add = a + b
end function add
end program bsp
|
Abstraktes Interface
Das bei der Deklaration eines Prozedurenzeigers als Schnittstelle genannte Unterprogramm muss nicht real implementiert sein. Es können statt dessen auch abstrakte Interfaces Verwendung finden. Diese sind gleich wie konventionelle Interface-Blöcke aufgebaut, mit dem Unterschied, dass sie als abstract interface gekennzeichnet sind. Ein mit einem abstrakten Interface deklarierter Prozedurzeiger passt dann für jedes Unterprogramm, welches mit identer Schnittstelle ausgestattet ist.
| Fortran 2003-Code |
program bsp
implicit none
abstract interface
function afunc( x, y )
integer :: afunc
integer, intent( in ) :: x, y
end function afunc
end interface
procedure( afunc ), pointer :: pptr1 => null()
procedure( add ) , pointer :: pptr2 => null()
pptr1 => add
write( *, * ) pptr1( 5 , 12 )
! Ausgabe: 17
pptr1 => mult
write( *, * ) pptr1( 3 , 2 )
! Ausgabe: 6
! Folgendes funktioniert uebrigens auch, da add() und mult() das gleiche Interface
! aufweisen:
pptr2 => mult
write( *, * ) pptr2( 5 , 5 )
! Ausgabe: 25
contains
function add( a, b )
integer :: add
integer, intent( in ) :: a, b
add = a + b
end function add
function mult( a, b )
integer :: mult
integer, intent( in ) :: a, b
mult = a * b
end function mult
end program bsp
|
Zeiger und das intent-Attribut
Nun ist bei der Übergabe von Zeigern an Unterprogramme auch die Angabe eines intent-Attributs möglich. Das war mit Fortran 90/95 noch nicht erlaubt. Diese intent-Angaben beziehen sich aber nicht auf die Variablenwerte an sich, sondern beschränken nur die Möglichkeiten zur Zeigerzuordnung im Unterprogramm selbst.
Beispiel:
| Fortran 2003-Code |
program bsp
implicit none
integer, target :: x = 15
integer, pointer :: ptr1 => null(), ptr2 => null()
ptr1 => x
ptr2 => x
call mult( ptr1, ptr2)
write( *, *) "Zuordnungsstatus ptr1:", associated( ptr1 )
write( *, *) "Zuordnungsstatus ptr2:", associated( ptr2 )
write( *, *) "Wert ptr1:", ptr1
write( *, *) "Wert x:", x
! Ausgabe:
! Zuordnungsstatus ptr1: T
! Zuordnungsstatus ptr2: F
! Wert ptr1: 45
! Wert x: 45
contains
subroutine mult( a, b )
integer, pointer, intent( in ) :: a
integer, pointer, intent( inout ) :: b
integer, target :: val = 3
! Folgendes waere nun nicht erlaubt, da a nur intent( in )
! a => null()
! Das auch nicht:
! a => val
! Das allerdings ist erlaubt:
a = a * val
! b ist mit intent( inout ) spezifiziert, also ist hier eine Zeigerzuordnung
! erlaubt:
b => null()
end subroutine mult
end program bsp
|
Zeiger und Felder
Auch im Zusammenspiel von Zeigern mit Feldern bringt der Fortran 2003-Standard einige Ergänzungen.
| <<< zur Fortran-Startseite | |
| << Fortran 2003 | Bibliotheken >> |
| < Datentypen | Ein- und Ausgabe > |