アプリ版:「スタンプのみでお礼する」機能のリリースについて

すみません。科学技術系の人間でして、フォートランが現役なのです。
あるプログラムのことですが、サブルーチンの内部の変数についてサブルーチンを呼び出すごとに加算していくようなことを行っています。
do i=1,100
call abc(i)   ← サブルーチンabcを100回呼び出す
enddo
end
subroutine abc(i)
n=n+1        ←呼び出されるたびに和をとる。
write(*,*) n
return
end
このようなシンプルなプログラムは問題ないのですが、少し複雑になるとどういうわけか、呼び出される度にnが初期化され、writeさせた結果常に1が表示されるという現象に会いました。
昔のコンパックフォートラン(MS-Fortran, DEC Fortranを継承)と、最近のIntel Fortran(最新版)で動作が異なります。前者では和を取ってくれますが、後者では初期化されて常に1が出力されます。(上記のプログラムは問題なしです。もう少し長いプログラムでの問題です。)
言語仕様の問題(すなわちフォートランのバージョン)なのか、コンパイラ仕様の問題なのか、C言語のように宣言の仕方で変ったりするようになったというようなことはないでしょうか。
以下に示すように和をとる変数をメインプログラム側に一旦見えるようにすると、インテル版でも思ったとおりの動作をします。
call abc(i,n)
suboroutine abc(i,n) としてnをメイン側に露出する。

よろしくお願いします。

A 回答 (3件)

元々のFORTRANの仕様で、サブルーチン内の変数は保証されなくてもかまいません。

これは、FORTRANの最初の仕様が決められた当時のコンピュータではメモリ容量が少なかったため、サブルーチンは呼び出される度にディスクからメモリにロードされていたため、変更された内容を保存する事ができなかったためです。これは、サブルーチンの変数をスタックに置かないGCOSのFORTRANなどでも同様です。

確実に値を保持したいなら、以下のいずれかの方法を使ってください。

・Nを引数に含める
・Nを名前無し共通領域(ブランクコモン)に置く
・Nを名前付き共通領域(レーベルドコモン)に置く
・SAVE文を使う
    • good
    • 0

初期化されていない、また保存もされていない変数は、


コンパイラが変われば扱いは変わりますし、コンパイル
オプションが変わっただけでも値が変わる性質のものです。
変数の扱い方に誤りがあると言わざるを得ません。

一般的に、サブルーチンが自分を呼び出した回数を計算する
こと自体、機能的強度の落ちる性質を持つように思われます。
複数の場所から呼び出すので仕方がない場合でも、なにか工
夫をしたいところです。

今回のケースに限って言えば、nの計算をする必要はなく、
目的の値はiにあります。
    • good
    • 0

局所変数は,実行時にスタックに積まれるのが普通ですから,変数の値は保持されなくても文句は言えません。

サブルーチン内で値を保持したい変数にSAVE属性を付けてあげましょう。
コンパイラのオプションで全ての変数をstaticにしてもよいですね。Intelコンパイラの場合は-saveか/Qsaveです。
昔の普通のコンパイラはsave属性がついているのがデフォルトでしたが,今は違います。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!