ポインタの挙動

fortran90のポインタの使い方がよくわかっていないので、テストプログラムを作成して実証してみる。

2つのファイルを用意して、モジュールのprivateな変数の演算結果をサブルーチンの引数を通して取得できるかテスト。

main.f90

program main
  use calc
  implicit none

  integer(kind=8) :: res
  integer(kind=8), pointer :: pnt

  allocate(pnt)
  call set_param

  res = 10
  call calc_param(res)
  write(*,'(a, i5)') "res = ", res

  !res = 0
  !call calc_pointer(res)
  !write(*,*) "res = ", res

  pnt = 10
  call calc_param(pnt)
  write(*,'(a, i5)') "pnt = ", pnt

  pnt = 10
  call calc_pointer(pnt)
  write(*,'(a, i5)') "pnt = ", pnt

end program main

calc.f90

module calc
  implicit none
  private
  public set_param, calc_param, calc_pointer

  integer(kind=8) :: a, b

  contains
subroutine set_param
  a = 1
  b = 2
end subroutine set_param

subroutine calc_param(c)
  integer(kind=8), intent(inout) :: c
  write(*,'(a, i5, a)') "c   = ",c,"  !! in calc_param"
  c = a + b
  write(*,'(a, i5, a)') "c   = ",c,"  !! in calc_param"
end subroutine calc_param

subroutine calc_pointer(c)
  integer(kind=8), pointer, intent(inout) :: c
  write(*,'(a, i5, a)') "c   = ",c,"  !! in calc_pointer"
  c = a + b
  write(*,'(a, i5, a)') "c   = ",c,"  !! in calc_pointer"
end subroutine calc_pointer

end module calc
FC=ifort
OBJS=calc.o

all: $(OBJS) main
main: main.o $(OBJS)
        $(FC) $(FCFLAGS) -o $@ $^

clean:
        $(RM) *.o *.mod
        $(RM) main

.SUFFIXES:
.SUFFIXES: .o .f90 .mod

.f90.mod:
        $(FC) -c -o $@ $<
.f90.o:
        $(FC) -c -o $@ $<

4つのパターンを用意しています。

  • 変数から変数に渡す
  • 変数からポインタに渡す
  • ポインタから変数に渡す
  • ポインタからポインタに渡す

この内の3番目のポインタから変数に渡すのは、コンパイル時にエラーになってしまいます。引数がポインタで定義されていれば変数を渡すことは出来ないようです。

ifort -c -o main.o main.f90
main.f90(16): error #6691: A pointer dummy argument may only be argument associated with a pointer.   [RES]
  call calc_pointer(res)
--------------------^
compilation aborted for main.f90 (code 1)
make: *** [main.o] Error 1


3番目をコメントアウトして実行した結果は、

c   =    10  !! in calc_param
c   =     3  !! in calc_param
res =     3
c   =    10  !! in calc_param
c   =     3  !! in calc_param
pnt =     3
c   =    10  !! in calc_pointer
c   =     3  !! in calc_pointer
pnt =     3

となりました。

ポインタを渡すときはサブルーチン側でもポインタでないといけないということがわかりました。

ソースコードの間違いで予期しない結果になっていたのに気づいて修正しました4/24)