Zum Inhalt springen

Fortran: Fortran 2003: Zeiger

Aus Wikibooks
<<< zur Fortran-Startseite
<< Fortran 2003 Bibliotheken >>
< Datentypen Ein- und Ausgabe >



Prozedurenzeiger

[Bearbeiten]

Einführung

[Bearbeiten]

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 (oder neuer)-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

[Bearbeiten]

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 (oder neuer)-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

[Bearbeiten]

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 (oder neuer)-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

[Bearbeiten]

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 (oder neuer)-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

[Bearbeiten]

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 >