2

非常に奇妙に書かれた約 400 行の Fortran 77 コードを継承しました。それを段階的に分析して、頭の中で明確にしようとしています。

とにかく、私はヘッダーのようなファイル(実際には.hですが、その中のコードは C/C++ ではなく fortran です)を持っていgetarg.hます。

character*80 serie
integer ln

次に、次のコードを含む別の fortran ファイル ( .f)を呼び出します。getserie.h

subroutine getserie(serie, ln)
include 'getarg.h'
call getarg(1, serie)
ln = index(serie, ' ') - 1
return
end

私の質問はcall、変数宣言だけを含む外部ファイルを作成できますか? これを行うことの効果は何ですか?

4

3 に答える 3

6

いいえ、サブルーチンのみを呼び出すことができます。これは、 として指定されたサブプログラムを意味しsubroutineます。ただし、サブルーチンの定義はソース ファイルにある必要はありません。リンク時に提供する必要があります。

getargサブルーチンはおそらく、コマンド ライン引数を取得するコンパイラの組み込みサブルーチンです。これは、コンパイラがサブルーチンのコードをリンカに自動的に提供することを意味します。

ファイルgetarg.hは決して呼び出されません。includeその内容は、ステートメントの場所に直接コピーされるだけです。

呼び出されたサブルーチンの (明示的な) インターフェースを使用できるようにする必要がある状況がありますが、それ以降の Fortran バージョンでは 90 以降です。これらの最新バージョンでは、通常、サブルーチンと関数をモジュールに配置して、コンパイラがそれらを正しく呼び出していることを確認できるようにします。

于 2012-11-01T14:43:23.693 に答える
1

ほとんどの FORTRAN実装に固有の機能の 1 つは、CALLほぼすべての外部シンボルを呼び出すことができることです。もちろん通話のみSUBROUTINEs は理にかなっています。これは、よく知られた FORTRAN の呼び出し規則 (実際の引数はすべてアドレスで渡される、つまり、サブルーチンに実際に渡されるすべての引数は同じ型であり、すべてポインターである) のため可能です。定数もアドレス (定数の値を含むメモリ位置のアドレス) で渡されます。これにより、コンパイラは、明示的なプロトタイプを提供する必要なく、任意のサブルーチンへの呼び出しを生成できます。すべての引数ポインターをスタックにプッシュするか (スタックベースの呼び出し規則を使用するプラットフォームの場合)、対応するレジスタにそれらをロードし (レジスタ呼び出し規則を使用するプラットフォームの場合) call、サブルーチンとして使用されるシンボルのアドレスにアセンブリ命令を発行します。の名前CALL声明。そのようなシンボルがリンク時に存在する場合、リンカーは実行可能ファイルを生成します。そうでない場合、未解決のシンボル参照についてエラーが発生し、実行可能ファイルは生成されません。

関数呼び出しについても同様です。配列インデックス操作からの関数呼び出しを伝えるためにコンパイラが使用する唯一の機能は、(非組み込み) 関数が として宣言されていることEXTERNALです。EXTERNAL関数を呼び出すための構文と配列の要素にアクセスするための構文は同じであるため、特別な指定が必要です。組み込み関数と呼ばれる、コンパイラによって内部的に認識される特別な定義済み関数もあります (例: SIN)。組み込みサブルーチンもありますが、それらのほとんどは単なるライブラリ サブルーチンです。

そのため、ステートメントに出くわし、そのCALL foo(...)内容がわからないときはいつでもfoo、コンパイラのマニュアルを参照して、この名前の組み込み関数が存在するかどうかを確認する必要があります。そうでない場合は、コードのどこかで定義されている可能性があります - を探してくださいSUBROUTINE foo。そうでない場合は、外部ライブラリからエクスポートされたサブルーチンであるか、プログラムにリンクされているか、または単なる構文エラーである必要があります。

サブルーチンが期待するものとはまったく異なるタイプの実引数を簡単に指定できたり、別の数の実引数を指定したとしてもコンパイラーは喜んでコードをコンパイルするため、これはすべて非常にエラーが発生しやすいものです。もちろん、そのようなプログラムは通常、実行時にクラッシュするか、無意味な結果を生成します。flintそのため、コンパイラが検出できない問題 (たとえば、引数の型の不一致、実際の引数の数の誤りなど) をソース コード全体でチェックするために、 のような特別なプログラムが開発されました。 Fortran 90 では、インターフェイスを導入することでこれを修正しています。インターフェイスは特定の状況では必須ですが、コンパイル時の引数チェックを提供するために一般的に使用できます。

于 2012-11-01T18:24:54.700 に答える
0

前述のように、ここで奇妙なのは、インクルードファイルの名前の選択が疑わしいことだけです。(.h拡張子と固有のシンボル名の無関係な使用の両方)。(はい、getargは標準的なf77ではなく、拡張機能です)

変数宣言をインクルードファイルに入れることは、プログラムユニット間で一貫した宣言を保証するための一般的な方法です(/以前は)。間違いなく、そのファイルは呼び出し元のプログラムにも「含まれ」、文字列がどこでも同じ長さで宣言されていることを確認します。

とはいえ、この例では、それは間違いなく不要です。文字列を想定される長さとして宣言できるため、includeの代わりに次のように配置します。

character serie*(*)
integer ln

メインプログラムでの通常の宣言と同様に、インクルードファイルの乱雑さを取り除きます。

(今、誰か​​が前世紀の初めに想定された長さの文字列宣言をサポートしていないコンパイラについて教えてくれます)。

于 2012-11-03T13:37:35.093 に答える