次のコードは、私が渡そうとしている割り当て可能な配列が正しく認識されていないため、セグメンテーション違反を返しています(サイズが3であるはずのサイズが1を返します)。このページ(http://www.eng-tips.com/viewthread.cfm?qid=170599)では、同様の例がF95で正常に機能することを示しているようです。私のコードファイルには.F90拡張子が付いていますが、それをF95に変更してみました。コンパイルにはgfortranを使用しています。
私の推測では、問題は割り当て可能な配列をサブルーチンに渡す方法にあるはずです。何が悪いのですか?
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%!
PROGRAM test
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%!
IMPLICIT NONE
DOUBLE PRECISION,ALLOCATABLE :: Array(:,:)
INTEGER :: iii,jjj
ALLOCATE(Array(3,3))
DO iii=1,3
DO jjj=1,3
Array(iii,jjj)=iii+jjj
PRINT*,Array(iii,jjj)
ENDDO
ENDDO
CALL Subtest(Array)
END PROGRAM
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%!
SUBROUTINE Subtest(Array)
DOUBLE PRECISION,ALLOCATABLE,INTENT(IN) :: Array(:,:)
INTEGER :: iii,jjj
PRINT*,SIZE(Array,1),SIZE(Array,2)
DO iii=1,SIZE(Array,1)
DO jjj=1,SIZE(Array,2)
PRINT*,Array(iii,jjj)
ENDDO
ENDDO
END SUBROUTINE
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%!
プロシージャに割り当て可能な仮引数がある場合、呼び出しスコープには明示的なインターフェイスが必要です。
(明示的なインターフェースを必要とするものは数多くありますが、割り当て可能なダミーは1つにすぎません。)
メインプログラム内にサブルーチンのインターフェイスブロックを配置することで、明示的なインターフェイスを自分で提供できます。代替のはるかに優れたオプションは、サブルーチンをモジュール内に配置し、そのモジュールをメインプログラムで使用することです。これにより、明示的なインターフェイスが自動的に作成されます。この例は、リンクを提供したeng-tipsサイトにあります。xwbによる投稿を参照してください。
割り当てステータスに関連する何かを行う場合(そのステータスのクエリ、再割り当て、割り当て解除など)を行う場合にのみ、仮引数が割り当て可能な属性を持つことは意味があることに注意してください。
また、割り当て可能な仮引数array
はintent(in)
で宣言されていることにも注意してください。これは、割り当てステータスが関連する実際の引数の割り当てステータスになることを意味します(手順中に変更することはできません)。サブルーチンに渡される実際の引数は、割り当てられていない可能性があるため、明示的なインターフェイスを使用していても、参照することはできません。コンパイラーはこれを認識せず、size
などの問い合わせの動作はそのような場合は未定義です。
したがって、内容を参照する前に、まずarray
の割り当て状況をallocated(array)
で確認する必要があります。さらに、lbound
とubound
を使用して配列全体にループを実装することをお勧めします。これは、一般にarray
の境界について確信が持てないためです。
subroutine subtest(array)
double precision, allocatable, intent(in) :: array(:,:)
integer :: iii, jjj
if(allocated(array)) then
print*, size(array, 1), size(array, 2)
do iii = lbound(array, 1), ubound(array, 1)
do jjj = lbound(array, 2), ubound(array, 2)
print*, array(iii,jjj)
enddo
enddo
endif
end subroutine
これは、モジュールで割り当て可能な仮引数を使用する簡単な例です。
module arrayMod
real,dimension(:,:),allocatable :: theArray
end module arrayMod
program test
use arrayMod
implicit none
interface
subroutine arraySub
end subroutine arraySub
end interface
write(*,*) allocated(theArray)
call arraySub
write(*,*) allocated(theArray)
end program test
subroutine arraySub
use arrayMod
write(*,*) 'Inside arraySub()'
allocate(theArray(3,2))
end subroutine arraySub