fortran66のブログ

fortran について書きます。

a(:) は必ずしも a ならず

配列の全配列操作を記述するとき、スカラーと配列を明示的に区別するために、配列名のあとに (:) をつけることが推奨されることがありますが、文脈によって微妙に意味が違う場合もあり、また副プログラム呼び出しの引数にしたときの挙動など、コンパイラの実装にも依存するので、時には注意が必要かと思います。

特に Fortran 2003 で、allocatable 属性の配列に代入するときの挙動がそれまでのものと変わって、自動再割り付けが行われたりするので危険です。

Cray が 2005 年に出した、Fortran 2003 and Beyond という Fortran 2003 規格と Fortran 2008 規格案を紹介した文書に、いい実例が出ていたので少し変えて紹介します。

ソース・プログラム

(:) があるとたとえ全部分を指定していても部分配列となり、自動再割り付けは行われません。(文字列の場合も同様です)

    program Console6
      implicit none
      block 
        character(len = :), allocatable :: string
        allocate(character(16)::string)
        string = '0123456789abcdef'
        !
        print *, len(string), ':', string, ':' ! length = 16
        string(:) = 'pad'
        print *, len(string), ':', string, ':' ! length = 16
        string = 'short'
        print *, len(string), ':', string, ':' ! lenght =  5
      end block
      !
      print *
      !
      block
        real, allocatable :: a(:), b(:), c(:)
        allocate(a(10), b(20))
        a = 1.10
        b = 1.20
        c = a
        print *, size(c)  ! size(c) = 10
        c = b
        print *, size(c)  ! size(c) = 20
        c(:) = a(:)       ! error size-mismatch
      end block
    end program Console6

実行結果

          16 :0123456789abcdef:
          16 :pad             :
           5 :short:

          10
          20
forrtl: severe (408): fort: (2): Subscript #1 of the array A has value 11 which is greater than the upper bound of 10

Image              PC        Routine            Line        Source
libifcoremdd.dll   5A1B4138  Unknown               Unknown  Unknown
Console6.exe       00C323AF  _MAIN__                    26  Console6.f90
Console6.exe       00C327DF  Unknown               Unknown  Unknown
Console6.exe       00C3521E  Unknown               Unknown  Unknown
Console6.exe       00C35100  Unknown               Unknown  Unknown
Console6.exe       00C34FAD  Unknown               Unknown  Unknown
Console6.exe       00C35238  Unknown               Unknown  Unknown
KERNEL32.DLL       73F68744  Unknown               Unknown  Unknown
ntdll.dll          774C587D  Unknown               Unknown  Unknown
ntdll.dll          774C584D  Unknown               Unknown  Unknown
続行するには何かキーを押してください . . .