LoginSignup
1
2

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-04-05

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

  • はじめに

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

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

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


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

1.まずはテストのために、このサブルーチンだけを呼び起こす(問題なしケース)

  program test

    call  main_qs

  end test
実行結果

  1 T

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

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

    program main

       call test

    end program
    subroutine test

      call  main_qs

    end subroutine test
実行結果
    1 F

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

  • とりあえずの解決策

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


subroutine main_qs( &
                !inout変数
                  )
  implicit none

  logical :: flag 

  flag = .true.

  !変数チェック
  write(6,*) '  2 ' , flag

  !メインとなるループ
  do while (flag)
    ....
  end do

end subroutine main_qs

実行結果

  2 T

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

問題解決

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

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

image.png

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

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

  • 実際に確認してみた!
デモ
  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言語でも試してみた!
デモ
  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 で初期宣言するときは気を付けていかないといけませんね。

1
2
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2