Fortran での bool値 の初期値宣言について、おかしなエラーがあったので呟いてみる【解決済】

#Fortran での bool値 の初期値宣言にまつわるエラー

- はじめに

fortran95 で以下のプログラムを作成中におかしなエラーに遭遇したので書いてみる。

  - 課題：　初期値を .true. で宣言したはずの変数flagが、勝手に .false. へとプログラム内で変更される 

まずはプログラムの内容から


```fortran

module mod_qs

public :: main_qs

contains
subroutine main_qs( &
                !inout変数
                  )
  implicit none
  
  logical :: flag = .true.


  !変数チェック
  write(6,*) '  1 ' , flag
  
  !メインとなるループ
  do while (flag)
    ....
  end do

end subroutine main_qs

end module
```

１．まずはテストのために、このサブルーチンだけを呼び起こす**（問題なしケース）**

 ```fortran
  program test

    call  main_qs

  end test
```

```fortran:実行結果
   
  1 T

 ```

初期宣言で True としてるので、こうなるはず！

２． 巨大なメインプログラムから呼び出したサブルーチン（親）内で、このサブルーチンを呼び出す**（問題ありケース）**


 ```fortran
    program main

       call test

    end program
 ```
 ```fortran
    subroutine test

      call  main_qs

    end subroutine test
```

 
 ```fortran:実行結果  
    1 F

 ```

初期宣言で True としてるはずなのに、なぜかプログラム内で勝手に**false**に置き換わってる！

 - とりあえずの解決策

 　＝＞　初期値をプログラム内で宣言することで正常動作

```fortran

subroutine main_qs( &
                !inout変数
                  )
  implicit none
  
  logical :: flag 

  flag = .true.

  !変数チェック
  write(6,*) '  2 ' , flag
  
  !メインとなるループ
  do while (flag)
    ....
  end do

end subroutine main_qs

```


```fortran:実行結果
   
  2 T

 ```


もちろん、bool 宣言ではなく、0,1のinteger や、初期化するモジュールないし場所をプログラムで設ければ問題は解決するはずですが、
よく、私自身logicalをプログラムで使うので、記事にまとめました。

# 問題解決

cure_honey さんから下記のようなアドバイスをいただきました。ありがとうございます！

結果的に、下記のコメントのとおり、**Fortranでは、サブルーチン内の変数宣言で初期化した値は、2回目以降の呼び出しでは反映されず、前回の操作結果の値を保持する（別個に初期値を設定する箇所を設ける必要がある）**という仕様？が原因となっていました。


![image.png](https://qiita-image-store.s3.amazonaws.com/0/247861/fd413b7a-579d-9d2c-389a-8c894e9728bb.png)


C言語等とは異なり、少し混乱するようなところでした。
まだまだFortranの勉強が足りないようです(笑)

簡単なデモ等を作成し、確認してみました。C言語でも同様のコードを作成し、違いを見てみました。その結果を下記に記載します。

- 実際に確認してみた！

```fortran:デモ
  1 program test
  2   implicit none
  3
  4   integer, parameter  :: n = 10
  5   integer             :: i
  6
  7   do i = 1, n
  8     call main_qs(  &
  9                  i & ! IN
 10                 )
 11   end do
 12
 13 end program test
 14
 15 subroutine main_qs(  &
 16                   ii & !  IN
 17                   )
 18   implicit none
 19
 20   integer,  intent(in)  :: ii
 21   logical               :: flag = .true.
 22   integer               :: j
 23
 24   write(6,*) 'Visit This SUB. Number ', ii  , ' FLAG ==  ', flag
 25
 26   do while ( flag )
 27     do j = 1, ii
 28         if ( j == ii  ) then
 29           flag = .false.
 30         end if
 31     end do
 32   end do
 33
 34   return
 35 end subroutine
```

```:実行結果
 Visit This SUB. Number            1  FLAG ==   T
 Visit This SUB. Number            2  FLAG ==   F
 Visit This SUB. Number            3  FLAG ==   F
 Visit This SUB. Number            4  FLAG ==   F
 Visit This SUB. Number            5  FLAG ==   F
 Visit This SUB. Number            6  FLAG ==   F
 Visit This SUB. Number            7  FLAG ==   F
 Visit This SUB. Number            8  FLAG ==   F
 Visit This SUB. Number            9  FLAG ==   F
 Visit This SUB. Number           10  FLAG ==   F
```

- C言語でも試してみた！

```c:デモ
  1 #include  <stdio.h>
  2 #include  <stdbool.h>
  3
  4 void main(void)
  5 {
  6   int n = 10;
  7   int i;
  8   for(i=0; i<n; i++  ){
  9     main_qs( i );
 10   }
 11 }
 12
 13 int main_qs( int ii  )
 14 {
 15   bool flag = true;
 16   int j = 0;
 17
 18   printf(" Visit This SUB. Number %d",ii ) ;
 19   printf(" FLAG  =  %d \n", flag ) ;-
 20
 21   while ( flag ){
 22     while( j <=  ii  ){
 23       if ( j == ii  ){
 24         flag = false;
 25       }
 26       j++;
 27     }
 28   }
 29 }
```

```:実行結果
 Visit This SUB. Number 0 FLAG  =  1
 Visit This SUB. Number 1 FLAG  =  1
 Visit This SUB. Number 2 FLAG  =  1
 Visit This SUB. Number 3 FLAG  =  1
 Visit This SUB. Number 4 FLAG  =  1
 Visit This SUB. Number 5 FLAG  =  1
 Visit This SUB. Number 6 FLAG  =  1
 Visit This SUB. Number 7 FLAG  =  1
 Visit This SUB. Number 8 FLAG  =  1
 Visit This SUB. Number 9 FLAG  =  1
```

ということで、fortran で初期宣言するときは気を付けていかないといけませんね。