2

Fortran では、適切な (整数) 範囲で配列を宣言できます。次に例を示します。

real* 8 array(-10:10)

Fortran は、参照渡しの場合、常に array(1) を参照として渡すと思いますが、よくわかりません。

私は fortran ポインターを使用していますが、fortran は配列 (-10) ではなく、「最初の」要素アドレス、つまり配列 (1) を指していると思います。しかし、よくわかりません。

Fortran はメモリ内の負の配列インデックスをどのように処理しますか? そして、それは定義されていますか?

編集: もう少し詳細を追加するために、Cie C 内から fortran ルーチンを呼び出すことによって行われるアドレスを指すために fortran ポインターを使用して、malloc されたブロックを C から fortran に渡します。

void * pointer = malloc(blockSize*sizeof(double));
fortranpoint_(pointer);

Fortran ポイント ルーチンは次のようになります。

real*8 :: target block(5, -6:6, 0:0)
real*8 :: pointer array(:,:,:)

entry fortranPoint(block)
array => block
return

問題は、後でアクセスしようとすると、次のように言うことがあります。

array(1, -6, 0)

これがブロックの先頭またはその前のどこかにあるアドレスにアクセスしているかどうかはわかりません。これは実装定義だと思いますが、各実装の詳細を知りたいです。

4

2 に答える 2

1

Fortran 配列引数 ABI はコンパイラに依存しますが、おそらくもっと重要なのは、呼び出されたプロシージャに明示的または暗黙的なインターフェイスがあるかどうかに依存します。

暗黙的なインターフェイスの場合、通常、最初の要素のアドレスが渡されます [1]。呼び出し先では、配列の仮引数の宣言方法に応じて、プロシージャによってオフセットが追加されます。たとえば、配列の仮引数が somearray(-10:10) と宣言されている場合、somearray(x) への参照は次のように計算されます。

address_of_first_element_passed_in_to_the_procedure + x + 10

プロシージャに明示的なインターフェイスがある場合、通常、最初の要素のアドレスではなく、配列記述子構造が渡されます。この構造体では、呼び出し先は各次元の境界に関する情報と、もちろん実際のデータへのポインターを見つけることができるため、暗黙的なインターフェイスの場合と同様に、正しいオフセットを計算できます。

[1] これはメモリ内の最初の要素、つまり各次元の最小インデックスであることに注意してください。配列がどのように宣言されたかに関係なく、 somearray(1) ではありません。

更新された質問に答えるには、C/Fortran の相互運用性について、現在広く利用されている ISO_C_BINDING 機能を使用します。これにより、C と Fortran の間で情報を受け渡す標準化された方法が提供されます。

于 2011-08-15T14:19:18.250 に答える
0

Fortranの通常の配列のダミー引数がA(:)(またはより多くの次元)で宣言されている場合、特定のインデックス範囲ではなく、SHAPEが渡されます。したがって、プロシージャはデフォルトで1つのインデックスになります。これは、A(-10 :)またはA(StartIndex :)のプロシージャの宣言でオーバーライドできます。ここで、StartIndexは別の引数です。

Fortranポインターにはインデックス範囲が含まれていますが、受け渡しメカニズムはコンパイラーに依存します。これをCに接続するコードは、OSとコンパイラに依存する可能性があります。すでに提案したように、私は通常の配列とISOCバインディングを使用します。これは、コンパイラの受け渡しメカニズムと標準および移植性を理解するための古い方法よりもはるかに簡単です。既存の大規模なFortranコードがある場合は、通常のFortran変数宣言とISOCバインディング名の間でマップする「接着」Fortranプロシージャを記述できます。これらのタイプの名前は正式には異なりますが、実際には、正しいISOCタイプを選択した場合は同じになります。ISO Cバインディングは何年も前から利用可能になっていますが、問題のあるターゲットプラットフォームでコンパイラをアップグレードできますか?そうでなければ、私は」

他のStackOverflowの質問でのISOCバインディングの使用例があります。

プロシージャへのインターフェイスは、呼び出し元のコンパイラに認識されるように宣言されている場合は明示的です。プロシージャをモジュールに配置し、呼び出し元でモジュールを「使用」する最も簡単な方法。コンパイラーは呼び出し元と呼び出し先の引数間の整合性をチェックできるため、明示的なインターフェースを使用するとバグを回避できます。これはCヘッダーファイルに少し似ていますが、簡単です。

于 2011-08-15T15:44:41.653 に答える