2010-12-06 4 views
5

Ich habe folgendes Programmkeeping Feldgrenzen in Fortran während Subroutinen-Aufruf

module test 
contains 
    subroutine foo() 
     integer, allocatable :: a(:) 
     allocate(a(-5:5)) 
     call bar(a) 
     print *, a 
    end subroutine 
    subroutine bar(a) 
     integer, intent(out) :: a(:) 
     a = 0 
     a(-4) = 3 ! here 
     a(2) = 3 
    end subroutine 
end module 

program x 
    use test 
    call foo() 
end program 

In der Zeile, die mit „hier“ ich etwas falsch mache. Tatsache ist, dass, wenn ich das Array a (in dem Anrufer von -5 bis +5 zugeordnet) erhält der Angerufene konventionelle Nummerierung (1 bis n) verwendet, was bedeutet, dass die Zuweisung -4 Ich mache eine außerhalb der Grenze Zuweisung. Wie kann ich dem Compiler mitteilen, dass innerhalb der bar Routine die Nummerierung des Arrays a mit der im Aufrufer übereinstimmen muss?

Antwort

4

Die Art der Scheinargument, die Sie mit der Dimension in der Unterroutine verwenden, sind mit einem Doppelpunkt angegeben, wird „angenommen Form“ bezeichnet. Dieser Name ist der Schlüssel - Fortran übergibt nur die Form und nicht die untere und obere Grenze. Die untere Grenze wird als Eins angenommen, es sei denn, Sie überschreiben sie, wie in der Antwort von kemiisto gezeigt. Wenn die untere Grenze nicht festgelegt ist, können Sie ein Argument übergeben, das als untere Grenze verwendet wird.

Später Zusatz: ein Codebeispiel, wenn die untere Dimension nicht zum Zeitpunkt der Kompilierung bekannt ist:

subroutine example (low, array) 
    integer, intent (in) :: low 
    real, dimension (low:), intent (out) :: array 
2

Wie kann ich dem Compiler mitteilen, dass innerhalb der Barroutine die Nummerierung eines Arrays die gleiche sein muss wie im Aufrufer?

Nicht sicher, aber gemäß dem Standard können Sie die untere Grenze für ein angenommenes Array festlegen.

subroutine bar(a) 
     integer, intent(out) :: a(-5:) 
+0

Was ist, wenn ich den Startindex zur Kompilierzeit nicht kenne? –

+0

@ Stefano: siehe M. S. B. Antwort. Sie benötigen die untere Grenze, um das zweite Argument Ihres Bar-Unterprogramms zu sein. – Wildcat

+0

Also ist die Anweisung 'integer, intent (out) :: a (lbound (a) :)' ungültig? (habe es nicht versucht, vielleicht sollte ich). Ich mag es nicht, Details über mein Array als Argument zu übergeben. –

3

Es gibt zwei Optionen:

  • Als kemisto schrieb, übergeben Sie ein zweites Argument . Dies war im Code im F77-Stil üblich. Du kannst den LBOUND-Trick nicht benutzen! Es muss als Integer übergeben werden.
  • Sie deklarieren das Argument als einen Zeiger, der den gesamten Array-Deskriptor enthält. Dann sind die Grenzen des Arrays in der Subroutine die gleichen wie im aufrufenden Bereich. Natürlich können Sie auf diese Weise die Optimierung verlieren.