Fortranで複数回呼ばれるルーチンの変数の初期化には気を付けよう！[ SAVE属性 ]

# 結論

- 複数回呼ばれるsubroutineやfunctionではSAVE属性ではない変数は宣言時の初期化をしてはいけない

# どうして変数の宣言時に初期化をしてはいけないか

- 変数の宣言時に初期化をすると、その変数は**自動的にSAVE属性になる**ため(お節介機能……)
- [このStackOverflowの回答](https://stackoverflow.com/questions/21418576/declaration-and-initialization-of-local-variables-in-fortran-pure-functions#:~:text=Under%20modern%20Fortran%20initialization%20implies%20SAVE.%20From%20F2008%205.2.3) を参照のこと

# SAVE属性
- SAVE属性を付けた変数に起こることは[ibm XL FortranのSAVE属性の記事](https://www.ibm.com/docs/ja/xl-fortran-aix/15.1.0?topic=attributes-save#:~:text=%E3%82%B5%E3%83%96%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E5%86%85%E3%81%A7%20RETURN%20%E3%81%BE%E3%81%9F%E3%81%AF%20END%20%E3%82%B9%E3%83%86%E3%83%BC%E3%83%88%E3%83%A1%E3%83%B3%E3%83%88%E3%81%8C%E6%A4%9C%E5%87%BA%E3%81%95%E3%82%8C%E3%82%8B%E6%99%82%E3%81%AB%E3%80%81SAVE%20%E5%B1%9E%E6%80%A7%E3%81%A7%E6%8C%87%E5%AE%9A%E3%81%95%E3%82%8C%E3%81%9F%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%83%BB%E3%82%A8%E3%83%B3%E3%83%86%E3%82%A3%E3%83%86%E3%82%A3%E3%83%BC%20(%E5%85%B1%E9%80%9A%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF%E4%BB%A5%E5%A4%96%E3%81%A7)%20%E3%81%8C%E5%AE%9A%E7%BE%A9%E6%B8%88%E3%81%BF%E7%8A%B6%E6%85%8B%E3%81%AB%E3%81%82%E3%82%8B%E5%A0%B4%E5%90%88%E3%80%81%E3%82%A8%E3%83%B3%E3%83%86%E3%82%A3%E3%83%86%E3%82%A3%E3%83%BC%E3%81%AF%E3%80%81%E3%81%9D%E3%81%AE%E3%82%B5%E3%83%96%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%8C%E6%AC%A1%E3%81%AB%E5%8F%82%E7%85%A7%E3%81%95%E3%82%8C%E3%82%8B%E6%99%82%E3%81%AB%E5%90%8C%E3%81%98%E5%80%A4%E3%81%A7%E5%AE%9A%E7%BE%A9%E3%81%95%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82%E4%BF%9D%E5%AD%98%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AF%E3%80%81%E3%82%B5%E3%83%96%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%AE%E3%81%99%E3%81%B9%E3%81%A6%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E3%81%AB%E3%82%88%E3%81%A3%E3%81%A6%E5%85%B1%E6%9C%89%E3%81%95%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82)に書いてある
- ibmの記事は少々難しい用語を用いて説明されているが、誤解を恐れず要約すると<br>**SAVE属性がついた変数は、一度変数を宣言したルーチンから抜けても<br>次に同じルーチンが走ったとき前回の値が保持された状態になる**という特徴がある
- しかも変数の宣言時の初期化処理は**最初の1回しか行われない**

**なのでSAVE属性にするつもりが無い変数で宣言時代入をすると<br>2回目以降の実行の結果が意図しないものになる!!!**

# 検証
- gfortran 9.3.0
- ファイル : main.f90 , sub.f90
- mainから10回subを呼んでsubで定義した数値 save_integer をインクリメントするプログラム

### プログラム

```fortran:main.f90
program main
    implicit none
    integer :: i

    do i = 1, 10
        call sub(i)
    end do
end program main
```

```fortran:sub.f90
subroutine sub(i)
    implicit none
    integer,intent(in) :: i
    integer :: save_integer = 0 ! この初期化処理は最初の1回しか実行されない！！

    save_integer = save_integer + 1
    print *, save_integer," main: ", i
end subroutine sub
```
### 結果

```shell:shell
gfortran main.f90 sub.f90 -o a.out && ./a.out

           1  main:            1
           2  main:            2
           3  main:            3
           4  main:            4
           5  main:            5
           6  main:            6
           7  main:            7
           8  main:            8
           9  main:            9
          10  main:           10
```

**上の結果からsave_integerにはSAVE属性を付けていないのに<br>integer :: save_integer = 0 が最初の1回しか実行されていないことがわかる**

# 解決策
- 変数の宣言とは別に初期値の代入を行う


```fortran:sub.f90
subroutine sub(i)
    implicit none
    integer,intent(in) :: i
    ! integer :: save_integer = 0 ! 宣言時に0を代入するのではなく……
    integer :: save_integer ! 宣言時は変数の宣言だけを行って
    save_integer = 0 ! 代入は別に行う!!!


    save_integer = save_integer + 1
    print *, save_integer," main: ", i
end subroutine sub
```

このように書くと……

### 結果

```shell:shell
gfortran main.f90 sub.f90 -o a.out && ./a.out

           1  main:            1
           1  main:            2
           1  main:            3
           1  main:            4
           1  main:            5
           1  main:            6
           1  main:            7
           1  main:            8
           1  main:            9
           1  main:           10
```

**subroutineが呼ばれるごとにsave_integer = 0 の処理が走るようになった！**

# 思ったこと

- Fortran以外の言語を触っている人ほど、宣言時代入をナチュラルに行ってバグらせそう
- SAVE属性使いたいなら明示的にinteger,save :: i = 0 とするんだから宣言時代入でなぜ自動的にSAVE属性にするのか？ｺﾚｶﾞﾜｶﾗﾅｲ