概要
(a ==1 && a== 2 && a==3)が真になるようなプログラムを,静的変数を使って実装したので投稿します.
Fortranの静的変数の宣言に驚くことと思います.
背景
前回の記事において,StackOverFlowで話題になっていた(a ==1 && a== 2 && a==3)が真になるようなプログラムをFortranで作りました.Fortranの規格あるいはコンパイラの実装の穴をつくような方法でしたので,別解として,穴をつかない方法で実装しました.この実装には静的変数を使いますが,Fortranでは静的変数の宣言の方法がC言語系統の言語とは異なります.配列が1始まりであるとか列優先であるとかで移植の際に色々と論争を巻き起こしますが,この静的変数の方が奇妙だと思っています.
実装
前回の記事と同じく派生型StrangeIntを使い,比較演算子==
をオーバーロードします.比較演算を実行する型束縛手続Equals
内では,正直にStrangeIntの値を変化させるのではなく,静的変数を宣言してその値と右辺値を比較するようにします.細かい実装については前回の記事を参考にしてください.
module class_StrangeInt
implicit none
private
type,public :: StrangeInt
integer :: value
contains
procedure,private,pass :: Equals
generic :: operator (==) => Equals
end type StrangeInt
contains
function Equals(this,criterion) result(isEqual)
implicit none
class(StrangeInt),intent(in) :: this
integer,intent(in) :: criterion
logical :: isEqual
integer :: i = 0
i = i + 1
isEqual = (i == criterion)
end function Equals
end module class_StrangeInt
戻り値を格納する論理型変数isEqual
の下に整数型変数i
を宣言し,1を足し,(i == criterion)
で右辺値と比較した結果を返します.特に難しいことをしているわけではありませんが,C言語系統に習熟している人が見ると,おや?と思うのではないでしょうか.
Fortranの静的変数
おや?と思うのはi
の変数宣言の所だと思います.C言語では,型名だけで宣言すると自動変数となり,変数が存在している関数が終了すると自動で解放されます.そして,宣言時に代入をしていると,実行毎にその値で初期化されます.関数を抜けても値を保持するようにするには,static
を付けて静的変数として宣言する必要があります.つまり,
int a = 0; //自動変数.寿命は関数が終わるまで.呼び出される度に0で初期化される.
static int a = 0; //静的変数.寿命はプログラムが終わるまで.0で初期化されるのは1度だけ.
という違いがあります.
Fortranでは,関数・サブルーチン内で変数宣言時に値を代入すると,その変数は静的変数になります.つまり,
integer :: a = 0 !静的変数.寿命はプログラムが終わるまで.0で初期化されるのは1度だけ.
integer :: a !自動変数.寿命は関数が終わるまで.
a = 0 !関数が呼び出される度に0で初期化される.
ということです.
複数の言語をさわる人は知っておいた方がよい知識でしょう.
ちなみに,Fotranには明示的に静的変数を宣言するsave
属性があるので,
- 基本的には変数宣言時に値を代入しない
- save属性を付与して静的変数である事を明示する場合のみ,宣言時に値を代入する
というルールを設けた方がよいと考えています.
動作テスト
前回の記事と同じメインルーチンを書いて実行してみましょう.
program main
use class_StrangeInt
implicit none
type(StrangeInt) :: a
if(a==1 .and. a==2 .and. a==3)then
print *,"TRUE"
end if
end program main
StrangeInt型の変数a
の値は全く参照しないので,代入すらしていません.
実行すると
TRUE
と表示され,この方法でも(a==1 .and. a==2 .and. a==3)
を真にすることができました.
まとめ
前回の記事に引き続き,(a==1 .and. a==2 .and. a==3)
が真になるようなプログラムのFortranで実装しました.派生型を宣言して比較演算子==
をオーバーロードし,比較演算を実行する型束縛手続内で静的変数と右辺値を比較するようにしました.
併せてFortranではローカル変数の宣言時に値を代入すると静的変数になるということも説明しました.古いFORTRAN/Fortranプログラムを他言語に移植しなければならず,四苦八苦している人の一助になれば幸いです.