36

良い習慣は、Fortranのサブルーチン引数がそれぞれ指定された意図を持っているべきであることを指示します(すなわちintent(in)intent(out)またはこの質問intent(inout)で説明されているように):

subroutine bar (a, b)
    real, intent(in) :: a
    real, intent(inout) :: b
    b = b + a
    ...

ただし、インテントを指定しないことは有効なFortranです。

subroutine bar (a, b)
    real, intent(in) :: a
    real :: b
    b = b + a
    ...

intent(inout)として指定された引数と指定された意図のない引数のコンパイル時チェック以外に実際の違いはありますか?インテントを古いインテントフリーのコードに後付けする場合、心配すべきことはありますか?

4

4 に答える 4

26

AdamsらによるFortran2003ハンドブックによると、intent(inout)引数と指定された意図のない引数の間には1つの違いがあります。intent(inout)の場合の実際の引数(つまり、呼び出し元)は、常に定義可能である必要があります。インテントが指定されていない場合、サブルーチンの実行でダミー引数を定義しようとすると、引数を定義可能にする必要があります定義可能値を設定することを意味します:dummy_arg=2.0。これが行われる場合、明らかに実際の引数は変数である必要があります。intent(inout)の場合、サブルーチンがこれを行うかどうかに関係なく、実際の引数は定義可能でなければなりません。意図が指定されていない場合は、サブルーチンの特定の呼び出しで何が発生するかによって異なります。サブルーチンで変数が定義されていない場合は、問題ありません。もしそうなら、問題があるよりも-定数である実際の引数に書き込むなどの場合は明らかに問題を引き起こします。

これは、コンパイラがこれらすべてのケースを診断することを意味するわけではありません。標準でコンパイラが診断する必要があるのは別の問題です。違反はコードの実行時のフローに依存するため、コンパイル時にインテントが指定されていないケース要件のすべてのエラーを検出することはほぼ不可能です。コンパイラーがintent(inout)ケースを診断し、コードの問題を警告する方がはるかに簡単です。

于 2010-05-21T14:38:28.230 に答える
7

あなたの質問は、あなたのコードがあなたのサブプログラムが書き込もうとする実際の引数としてPARAMETERを渡した場合にあなたが振る舞いの違いに遭遇するかもしれないかどうか疑問に思うように私に促します。INTENT宣言がないと、コンパイラはこれを手放し、奇妙な動作を引き起こす可能性があります。宣言では、コンパイル時のエラーが予想されます。

あなたと私は、INOUT宣言とINTENT宣言に違いはないと思うかもしれませんが、古いFortranプログラムがたくさんあり、古い言語バージョンとの互換性が新しい標準の重要な機能であることを忘れないでください。FORTRAN77が正しかった(しかし危険な)場合、多くの人は、Fortran 90+コンパイラーでコードが正しい(まだ危険な)ままであると期待しています。

2003規格をざっと読むと、INOUTとINTENTなしの間に違いがあることがわかりますが、もっと詳しく読む必要があります。これをテストする場合は、結論をお知らせください。後で時間があれば、自分でテストしてお知らせします。

于 2010-05-21T09:03:06.677 に答える
4

インテントイン/アウトの役割を理解するには、内部的に、Fortranが参照によって変数を効果的に渡すことを知っておく必要があります。これは、実際に参照を渡すことと必ずしも同じではありません。

2次元配列の内部サブセクションをサブルーチンに渡す場合、つまり:data(i1:i2, j1:j2)の場合、Fortranはそのデータをメモリの連続するセクションにコピーし、新しいアドレスをルーチンに渡します。戻ると、データは元の場所にコピーされます。

を指定することによりINTENT、コンパイラはコピー操作の1つをスキップすることを知ることができます。

これは、変更しないままにしておきたいデータを変更するためのフェイルセーフとして機能するだけでなく、大規模なデータセットを処理するときにコードを高速化することもできます。

于 2016-04-14T21:40:53.427 に答える
0

どういうわけかMSBの答えを拡張するために、省略intentすると、コンパイル時のチェックが少なくなりますが、柔軟性が高まります。がないintentと、コードブランチがリテラル定数を変更しようとしないことがわかっている場合は、リテラル定数を渡すことができますintent(inout)。これを試みると、コンパイラーが吠える可能性があります。これは、オプションに応じて一部の引数を変更するかどうかを決定する「デュアル」プロシージャで役立つ場合があります。次に例を示します。

subroutine copy(x,a,readwrite)
integer :: x, a
integer, intent(in) :: readwrite

if (readwrite == 0) then
  x = a
else
  a = x
end if

end subroutine

とを追加する場合は、両方が読み取られて変更される可能性があるため、両方に追加intentする必要がありますx。しかし、それはあなたが例えば書くことを可能にしませんainout

call copy(x,3,0)  ! equiv. to x=3
call copy(42,a,1) ! equiv. to a=42

この例は非常にばかげていますが、複雑なフォーマットのファイルからの読み取りまたはファイルへの書き込みが可能な、より複雑なサブルーチンについて考えてみてください。(これが最善の解決策だと言っているわけではありませんが、簡単に見つけることができます。)

于 2021-09-29T09:43:19.537 に答える