Fortran 95/90 では、配列を配列要素、配列サブセクション、または配列名で参照される配列全体として渡すことができます。Fortran では、配列要素は列優先順に編成されていて、最初の添字 (次元) から優先されます。
Fortran と他の言語の間で配列を使用する場合、要素のインデックスと順序を考慮する必要があります。配列要素は個別に参照し、追跡する必要があります。Fortran および C では、配列要素のインデックス付けの方法が異なります。配列のインデックス付けは、ソースレベルでの問題であり、下位のデータに違いはありません。
Fortran および C の配列は、次の 2 つの点で異なります。
配列の下限の値が異なります。デフォルトでは、Fortran は配列の先頭の要素のインデックスを 1 とします。C および C++ では、0 とします。したがって、Fortran の添字は 1 つ大きい値に設定しなければなりません。(Fortran には、別の整数で下限を指定するオプションもあります)。
多重次元配列の場合、Fortran は最も左のインデックスから優先するのに対し、C では最も右のインデックスから優先します。これは、それぞれ列優先順および行優先順と呼ばれることがあります。
C では、X[3][3] として宣言されている配列の最初の 4 つの要素は次のとおりです。
X[0][0] X[0][1] X[0][2] X[1][0]
一方、Fortran では、最初の 4 つの要素は次のとおりです。
X(1,1) X(2,1) X(3,1) X(1,2)
インデックスの順序は、次元をいくつ宣言しても同じです。例えば、次の C の宣言の場合、
int arr1[2][10][15][20];
これは Fortran の次の宣言に相当します。
INTEGER arr1( 20, 15, 10, 2 )
C の配列宣言に使用される定数は、他の言語のように上限ではなく、範囲を表しています。このため、int arr[5][5] と宣言された C 配列の最後の要素は、arr[5][5] ではなく arr[4][4] となります。
次の表に、対応する配列宣言を示します。
異なる言語で対応する配列宣言
言語 |
配列宣言 |
Fortran からの配列参照 |
---|---|---|
Fortran |
DIMENSION x(i, k) |
x(i, k) |
C/C++ |
type x[ k ] [ i ] |
x( i -1, k -1) |
Fortran 95/90 が複数のポインタ・メモリ・アドレスを追跡しなければならない場合に備えて、インテル Fortran コンパイラは、配列の編成に関する詳細情報を格納する配列記述子 を使用します。
(結合またはプロシージャ・インターフェイス・ブロックによる) 明示的なインターフェイスを使用する場合 、インテル Fortran は次の形式の配列引数記述子を生成します。
配列へのポインタ (配列ポインタ)
形状引継ぎ配列
一部のデータ構造体引数は、適切な明示的インターフェイスが提供されている場合でも、記述子を使用しません。例えば、明示的形状配列および大きさ引継ぎ配列は記述子を使用しません。一方、配列ポインタおよび割付け配列は、引数として使用するかどうかに関わらず、記述子を使用します。
インテル Fortran と Fortran 以外の言語 (C など) の間で呼び出しを行う場合、暗黙的インタフェースを使用することで、インテル Fortran の記述子なしで配列を渡すことができます。ただし、呼び出されたルーチンがインテル Fortran 記述子に含まれる情報を必要とする場合、ルーチンを明示的インタフェースで宣言し、仮配列を形状引継ぎ配列として、またはポインタ属性で指定します。
Fortran 95/90 ポインタは、(配列境界が "矩形" である限り) 任意の形式で編成された任意のメモリ部分と関連付けることができます。また、Fortran 95/90 ポインタを C などの他の言語に渡し、その言語で記述子を正しく解釈して、必要な情報を取得することができます。
ただし、配列記述子を使用すると、エラーが起こる可能性が高くなります。また、対応するコードの移植性も損なわれます。特に、次のことに注意してください。
記述子が正しく定義されていない場合、プログラムは間違ったメモリアドレスを参照し、一般保護違反を発生させることがあります。
配列記述子の書式は、各 Fortran コンパイラに対して固有です。配列記述子を使用するコードは、他のコンパイラやプラットフォームへ移植できません。例えば、現在のインテル Fortran の配列記述の書式は、インテル Fortran 7.0 の配列記述の書式と異なります。
配列記述子の書式は、将来変更される可能性があります。
次に、IA-32 システム上における現在のインテル Fortran の配列記述子のコンポーネントを示します。
最初のロングワード (バイト0 から 3) には、ベースアドレスが含まれています。ベースアドレスとオフセットで、配列の最初のメモリ位置 (開始) を定義します。
2 番目のロングワード (バイト 4 から 7) には、配列の 1 つの要素のサイズが含まれています。
3 番目のロングワード (バイト 8 から 11) には、オフセットが含まれています。オフセットをベースアドレスに加えて、配列の開始位置を定義します。
4 番目のロングワード (バイト 12 から 15) には、配列が定義されている (記憶領域が割り当てられている) 場合に設定される下位ビットが含まれています。また、例えば連続した配列を示す場合などで、その他のビットもこのロングワード内でコンパイラによって設定される可能性があります。
5 番目のロングワード (バイト 16 から 19) には、配列の次元 (次元数) が含まれています。
6 番目のロングワード (バイト 20 から 23) は、予約済みです。
残りのロングワード (バイト 24 から 107) には、個々の (最大 7 つまでの) 次元に関する情報が含まれています。各次元は、さらに 3 つのロングワードによって記述されます。
要素の数 (範囲)
この次元で連続する 2 つの要素の開始アドレス間の距離 (バイト数)
下限
次元数 1 の配列は、3 つのロングワードを追加する必要があるため、合計で 9 つのロングワード (6 + 3*1) が含まれ、バイト 35 で終わります。次元数 7 の配列は、合計で 27 のロングワード (6 + 3*7) が含まれ、バイト 107 で終わります。
例えば、次のような宣言の場合を考えてみます。
integer,target :: a(10,10) integer,pointer :: p(:,:) p => a(9:1:-2,1:9:3) call f(p)
.
.
.
実引数 p の記述子は、次の値が含まれます。
最初のロングワード (バイト0 から 3) には、ベースアドレスが含まれます (ランタイムで割り当てられます)。
2 番目のロングワード (バイト 4 から 7) は、4 (1 つの要素のサイズ) に設定されます。
3 番目のロングワード (バイト 8 から 11) には、オフセットが含まれています (ランタイムで割り当てられます)。
4 番目のロングワード (バイト 12 から 15) には、1 が含まれます (下位ビットが設定されます)。
5 番目のロングワード (バイト 16 から 19) には、2 が含まれます (次元数)。
6 番目のロングワードは、予約済みです。
7、8、および 9 番目のロングワード (バイト 24 から 35) には、最初の次元に関する次の情報が含まれています。
5 (範囲)
-8 (要素間の距離)
9 (下限)
10、11、および 12 番目のロングワード (バイト 36 から 47) には、2 番目の次元に関する次の情報が含まれています。
3 (範囲)
120 (要素間の距離)
1 (下限)
この例では、バイト 47 が最後のバイトとなります。
注
Itanium ® ベース・システムの指定子の書式は、IA-32 システムの書式と同じですが、すべてのフィールドが 4 バイトから 8 バイトになります。