1. 導入:なぜ配列の受け渡しでエラーが起きるのか?
Fortranで数値計算を行う際、配列をサブルーチンに渡す場面は非常に多いです。しかし、配列のサイズを柔軟に扱おうとして「想定形状配列(Assumed-shape array)」を使った途端、「コンパイルエラーになる」「実行時に値がおかしくなる」という経験はありませんか?
これらは、プログラムが「受け取る側の配列の形」を正しく認識できていないことが原因です。本記事では、現代のFortran開発で必須となる「インタフェース」の重要性と、安全な配列の受け渡し方法を解説します。
2. 基礎知識:想定形状配列とインタフェースとは
想定形状配列とは、サブルーチンの引数定義で `real, intent(in) :: arr(:)` のように、サイズを `(:)` と書くことで、呼び出し元から渡された配列のサイズをそのまま受け取る仕組みです。
しかし、単に引数に書くだけでは不十分です。Fortranコンパイラは、呼び出し元と呼び出し先の「引数の型や形状」が一致しているかを確認する必要があります。この確認役を果たすのがインタフェースです。
現代のFortranでは、サブルーチンをモジュール(`module`)内に配置し、`use`文で読み込むことで、自動的にインタフェースが提供されます。これがないと、コンパイラは「渡されたデータが配列なのか、それとも単なる数値なのか」を判断できず、メモリ破壊などの深刻なバグを引き起こすリスクがあります。
3. 実装/解決策:モジュールを活用した安全な連携
配列を安全に渡すための鉄則は「モジュール化」です。
1. 計算用のサブルーチンを `module` 内に記述する。
2. 呼び出し側では `use` 文を使ってモジュールをインポートする。
これだけでコンパイラがインタフェースを認識し、型チェックや形状チェックを自動で行ってくれるようになります。
4. サンプルプログラム
以下のコードをコピーして、`my_mod.f90` と `main.f90` として保存し、コンパイルして実行してみてください。
! --- モジュール定義 ---
module my_mod
contains
! 想定形状配列を引数にとるサブルーチン
subroutine compute_proc(arr)
real, intent(in) :: arr(:) ! 渡された配列のサイズを自動認識
integer :: i
print , "配列の合計値を計算します..."
print , "要素数: ", size(arr)
print , "合計値: ", sum(arr)
end subroutine compute_proc
end module my_mod
! --- メインプログラム ---
program main
use my_mod, only : compute_proc
real :: data(5) = [1.0, 2.0, 3.0, 4.0, 5.0]
! インタフェースが既知であるため、安全に配列を渡せる
call compute_proc(data)
! スライシング(一部だけ渡す)も可能
print , "一部(1〜3要素目)で計算:"
call compute_proc(data(1:3))
end program main
5. 応用・注意点:現場で役立つヒント
・スライシングの注意点
`data(1:3)` のように配列の一部を渡す際、インタフェースが正しく定義されていないと、コンパイラは内部的に「一時的なコピー」を作成するか、あるいは意図しないメモリ領域を参照して誤作動することがあります。モジュールを使っていれば、コンパイラが最適化を行い、正しく処理してくれます。
・インタフェースブロックの明示
もし何らかの理由でモジュールが使えない古いコード(レガシーなソース)を改修する場合は、`interface` 文を使って手動でインタフェースを定義する必要があります。しかし、現代の開発では、可能な限りすべてのサブルーチンをモジュール内に収めるのが、最も安全でバグの少ない開発手法です。
まずは「サブルーチンは必ずモジュールに入れる」という習慣を身につけるだけで、Fortranの配列演算は劇的に安定します。

コメント