ナビゲーション:前へ 上へ 次へ
10.8 プログラムと手続 [大部分 5.3]
- CONTAINS文の後に空の内部副プログラム部分、モジュール副プログラム部分、 及び型束縛手続部分の記述が許されるようになりました。 型束縛手続部分の場合では(特に効果のない)PRIVATE文が (指定する必要のない)CONTAINS文の後に許されるようになりました。
-
[6.0]
内部手続が実引数として渡せます。また手続きポインタへ代入もできます。
内部手続が仮引数経由もしくは手続きポインタ経由で実行された場合に、
親手続きの局所変数へのアクセスが可能となりました。
手続きポインタの場合には、ポインタは親手続が復帰するまでの間のみ有効です。
(これは局所変数がそれ以降存在しなくなるからです)
例)
SUBROUTINE mysub(coeffs) REAL,INTENT(IN) :: coeffs(0:) ! Coefficients of polynomial. REAL integral integral = integrate(myfunc,0.0,1.0) ! Integrate from 0.0 to 1.0. PRINT *,'Integral =',integral CONTAINS REAL FUNCTION myfunc(x) RESULT(y) REAL,INTENT(IN) :: x INTEGER i y = coeffs(UBOUND(coeffs,1)) DO i=UBOUND(coeffs,1)-1,0,-1 y = y*x + coeffs(i) END DO END FUNCTION END SUBROUTINE
-
Fortran 2008のルールが総称解決と総称内手続のあいまいさの判断に使われるようになりました。
このルールでは:
- 仮手続は仮引数と区別が可能です。
- ALLOCATABLE仮変数はINTENT(IN)を持つPOINTER仮変数と区別可能です。
- [6.0] 遊離状態のポインタ及び割付られていない割付け変数は省略可能な非割付、非ポインタ仮引数に対しての実引数として渡す事ができます。 この場合実引数が存在していないかのように処理されます。
-
[5.3.1]
非純粋要素別処理手続はIMPUREキーワードを用いてが定義可能です。
非純粋要素別処理手続は要素別であるが故の制限(例えばすべての引数がスカラでなければならない)がありますが、“純粋”に関しても制限はありません。
これは非純粋要素別処理手続きに副作用があり得る事と、入出力及びSTOP文を含み得る事を意味します。
例)
Impure Elemental Integer Function checked_addition(a,b) Result(c) Integer,Intent(In) :: a,b If (a>0 .And. b>0) Then If (b>Huge(c)-a) Stop 'Positive Integer Overflow' Else If (a<0 .And. b<0) Then If ((a+Huge(c))+b<0) Stop 'Negative Integer Overflow' End If c = a + b End Function
引数が配列の場合、それぞれの成分に対して非純粋手続きが配列成分順に適用されます。 (これは特に順番が定められていない純粋要素別手続きとは異なります) 非純粋手続きは手続きが純粋でなければならない状況(例:FORALL構文内)では参照できません。非純粋要素別手続きはおそらく最終手続きと(入出力が許されているという理由により)デバッグ時に最も有用です。
-
[6.0]
純粋手続きの引数がVALUE属性を持つ場合、どのINTENT属性も必要ありません。
例)
PURE SUBROUTINE s(a,b) REAL,INTENT(OUT) :: a REAL,VALUE :: b a = b END SUBROUTINE
しかしながら、利用者定義代入サブルーチンの二番目の引数と利用者定義演算のすべての引数はこの限りではなく、VALUE属性を持つ場合でもINTENT(IN)属性を指定しなければなりません。
- [5.3.1] 内部手続及びモジュール手続において、 END文の FUNCTION 及び SUBROUTINE キーワードが省略可能となりました。(手続名も指定しない場合のみ) 今までは外部手続でのみ省略可能でした。
- ENTRY文は削除予定機能として扱われます。
- [1.0] プログラム内の行がセミコロンで始まっても良くなりました。
-
[6.2] 結合名を持つ外部手続きの名前が大域識別子ではなく局所識別子として取り扱われるようになりました。
これが意味するのは、例えば以下のようなコードが標準準拠になったという事です。
SUBROUTINE sub() BIND(C,NAME='one') PRINT *,'one' END SUBROUTINE SUBROUTINE sub() BIND(C,NAME='two') PRINT *,'two' END SUBROUTINE PROGRAM test INTERFACE SUBROUTINE one() BIND(C) END SUBROUTINE SUBROUTINE two() BIND(C) END SUBROUTINE END INTERFACE CALL one CALL two END PROGRAM
- [6.2] NAME=指示子を持たない場合に限り、 内部手続がBIND(C)属性であっても許容されます。 このような手続きはCと相互運用可能ですが(NAME=''で指定するような)結合名を持ちません。
-
[6.2]
VALUE属性を持つ仮引数が配列であっても許容されます。
また非定数及び/又は1ではない長さのCHARACTER型であっても許容されます。
(ALLOCATABLE又はPOINTER属性を持つ事は依然として許容されません。
また共配列も許容されません。)
結果としては実引数の複製が作られ、仮引数はその複製と結合されます。 仮引数への変更は実引数に影響を及ぼしません。 例えば
PROGRAM value_example_2008 INTEGER :: a(3) = [ 1,2,3 ] CALL s('Hello?',a) PRINT '(7X,3I6)',a CONTAINS SUBROUTINE s(string,j) CHARACTER(*),VALUE :: string INTEGER,VALUE :: j(:) string(LEN(string):) = '!' j = j + 1 PRINT '(7X,A,3I6)',string,j END SUBROUTINE END PROGRAM
は以下を出力します。Hello! 2 3 4 1 2 3