3

Fortran コードを解読しようとしています。関数へのポインターを実引数として渡し、代わりに仮引数がターゲットになります。メイン プログラムで globalDATA 型のポインターを定義して割り当て、そのポインターを渡す関数を呼び出します。

module dataGLOBAL
 type globalDATA
   type (gl_1)      , pointer :: gl1
   type (gd_2)      , pointer :: gd2
   type (gdt_ok)    , pointer :: gdtok
   ...
   ...
 end type globalDATA
end module dataGLOBAL


Program main
....
....
use dataGLOBAL   
...
type(globalDATA),pointer :: GD

allocate(GD)
returnvalue = INIT(GD)
....
....
end

関数は次のとおりです。

integer function INIT(GD) result(returnvalue)
....
....
use dataGLOBAL

type(globalDATA)  , target   :: GD

allocate (GD%gl1)
allocate (GD%gd2)
allocate (GD%gdtok)
....
....
end function INIT

これを行う意味は何ですか?また、メイン プログラムのポインタとターゲット構造の単一コンポーネントの両方を割り当てる必要があるのはなぜですか? ありがとうA。

4

3 に答える 3

9

いくつかのことが関係するかもしれません...

  • 対応する仮引数が POINTER 属性を持たないプロシージャーへの実引数としてポインターを提供する場合 (この場合)、仮引数に関連付けられているものは、実引数ポインターのターゲットです。したがって、この場合、渡されるのは、GD(メインプログラムで) が指しているオブジェクト、つまり、allocate ステートメントによって割り当てられたものです。(実引数と仮引数の両方に POINTER 引数がある場合、POINTER 自体が「渡され」ます。POINTER が指すものを変更でき、その変更は呼び出しスコープに反映されます。)

  • 関数内のGD仮引数には target 属性があるため、関数内のポインターは仮引数を指すことができます。そのようなポインターの宣言は表示されませんが、おそらくそれらは省略されたコードにあります。仮引数 (INIT 関数によって呼び出される可能性のあるプロシージャー内を含む) が何も指されていない場合、TARGET 属性は不必要ですが、いくつかの最適化を禁止することを除けば害はありません。GD

  • ポインター属性を持つものも (言語規則によって自動的に) TARGET 属性を持つためGD、メイン プログラムには TARGET 属性があります。GDメインプログラムと関数の両方にターゲット属性があるという事実は、関連している可能性があります...

  • 仮引数に TARGET 属性があり、実引数として渡されたものに TARGET 属性がある場合、プロシージャ内の仮引数に関連付けられたポインターも「通常」です (例外があり、同時インデックス化されたもの/連続していないものにはプロセッサの依存関係があります)。配列/ベクトル添字セクションは複雑すぎて覚えられません) 対応する実引数に関連付けられています。ポインターがローカル変数でない場合 (おそらくモジュールで宣言されたポインター)、この関連付けはプロシージャーの終了後も存続します。おそらく、それは省略されたコードに関連しています。(あるいは、実引数に TARGET 属性がない場合、仮引数に関連付けられたすべてのポインターは、プロシージャーの終了時に未定義になります。)

  • 型のコンポーネントglobalDATA自体がポインターです。したがって、GDメイン プログラムには、他のもの (関数内の多数の ALLOCATE ステートメントによって割り当てられる他のもの) へのポインターを含む何か (メイン プログラムの単一の ALLOCATE ステートメントによって割り当てられるもの) へのポインターがあります。2 レベルのポインターがあるため、2 レベルの ALLOCATE があります。

  • Fortran 2003 (または「割り振り可能な TR」を備えた Fortran 95) より前は、派生型に ALLOCATABLE コンポーネントを含めることはできず、ALLOCATABLE ダミー引数を含めることもできませんでした。ポインターを値としてのみ使用していたとしても、代わりにポインターを使用してください。私はあなたのコードがこの時代のものであると強く疑っています (割り当て可能な TR のサポートは約 10 年前に広まりました)。非常に「現代的な」Fortran ポインターは、他のものを指す変数が必要な場合にのみ使用されます (他のものには「何も含まれていません」)。

于 2013-01-07T02:40:04.937 に答える
2

それ自体がポインターを含むユーザー定義型のポインター変数では、変数全体とコンポーネント ポインターの両方を割り当てる (つまり、ストレージを作成する) 必要があります。全体の変数が割り当てられている場合、コンポーネントは自動的に割り当てられません。誰かが、全体の変数をメイン プログラムに割り当て、コンポーネントをサブルーチンに割り当てるという設計上の選択を行いました。変数全体を割り当てるのは簡単だと思っていたのかもしれませんが、すべてのコンポーネントを割り当てるのは複雑になり、それをサブルーチンに委ねたいと考えました。

于 2013-01-07T02:23:36.333 に答える
0

仮引数にはポインター属性が指定されていないため、派生型全体GDがメイン コードから渡されます (それへのポインターではありません)。サブルーチン側では、明示的に書くことができます

integer function INIT(GD) result(returnvalue)
...
use dataGLOBAL

type(globalDATA), intent(inout), target :: GD

より明確にするために。仮引数の target 属性は、ポインター割り当てを介してサブルーチンでその引数を指すことができることのみを保証します。

INIT派生型のフィールドのみを操作し、派生型全体を (たとえば、割り当てまたは解放によって) 操作しない限り、ポインターを渡すことによってルーチンを呼び出すか、派生型を渡すことによってルーチンを呼び出すかどうかに違いはありません。自体。

他の回答ですでに述べたように、プログラムの目的は、派生型とそのコンポーネントの割り当てを互いに分離しているようです。この戦略の考えられる利点の 1 つは、ポインターと静的に割り当てられた派生型の両方をINITルーチンに渡すことができることです。

于 2013-01-07T12:24:58.963 に答える