配列と Visual Fortran 配列記述子の処理

Fortran 95/90 では,配列を配列要素として,部分配列として,または配列名で引用される配列全体として渡すことができます。Fortran 95/90 の中では,配列要素は列主順で並べられており,最も下の次元の添字が先に変化します。

Fortran と他の言語の間で配列を使用するときには,要素の索引付けと順序を考慮に入れる必要があります。配列要素は個別に引用し,追跡しなくてはなりません。Fortran,Visual Basic,MASM,および C では,配列要素の索引付けの方法が異なります。配列の索引付けはソース・レベルでの問題であり,下位のデータに違いはありません。

Visual Basic は配列と文字列を記述子,すなわち配列の大きさと位置を含んでいるデータ構造として格納します。ただし,この記憶形態の違いはユーザーからは見えません。

Visual Basic から Fortran に配列を渡すには,配列の最初の要素を渡します。基本設定では,Visual Basic は変数を参照によって渡すので,配列の最初の要素を渡すと,Fortran には Fortran が期待しているとおりに,配列の開始位置が与えられます。Visual Basic は基本設定では最初の配列要素の索引を 0 としますが,Fortran は基本設定では 1 とします。次の文を使えば,Visual Basic の索引付けを 1 から開始させることができます。

	Option Base 1

別の方法として,どちらの言語でも,配列宣言中で,配列の下限を -32,768 ~ 32,767 の範囲の任意整数に設定することができます。次に例を示します。

Basic コード:

	Declare Sub FORTARRAY Lib "fortarr.dll" (Barray as Single)
	DIM barray (1 to 3, 1 to 7) As Single
	Call FORTARRAY(barray (1,1))

Fortran コード:

	Subroutine FORTARRAY(arr)
	  REAL arr(3,7)

MASM では,配列は 1 次元であり,配列要素はバイト単位に引用しなくてはなりません。機械語は配列の要素をメモリー内に連続して格納し,最初のアドレスが配列名によって引用されます。個々の要素を参照するには,最初の要素を基準として,目的の要素の前にある要素の合計バイト数を読み飛ばします。次に例を示します。

	xarray REAL4 1.1, 2.2, 3.3, 4.4 ; initializes
					; a four element array with
					; each element 4 bytes

MASM での xarray の引用は最初の要素,すなわち 1.1 を含んでいる要素を引用します。第 2 の要素を引用するには,最初の要素の 4 バイト後にある要素を,xarray[4] または xarray+4 で引用する必要があります。次に別の例を示します。

	yarray BYTE 256 DUP	; establishes a
				; 256 byte buffer, no initialization
	zarray SWORD 100 DUP(0)	; establishes 100
				; two-byte elements, initialized to 0

Fortran と C の配列は 2 つの点で異なります。

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)
または
type x(i, k)
x(i, k)
Visual Basic DIM x(i, k) As type x( i - 1, k - 1 )
Visual C/C++ type x[ k ] [ i ] x( i - 1, k - 1 )
MASM 配列は連続した記憶域にある要素として宣言し引用する。

Visual Fortran の配列記述子書式

Fortran 95/90 が複数のポインタ・メモリー・アドレスを追跡しなければならない場合に備えて,Visual Fortran コンパイラは,配列の編成の詳細を格納する配列記述子を使用します。

(結合または手続インタフェース宣言による) 明示的なインタフェースを使用する場合,Visual Fortran は次の形式の配列引数記述子を生成します。

一部のデータ構造引数は,適切な明示的インタフェースが提供されている場合でも記述子を使用しません。たとえば,明示的整形配列と大きさ引継ぎ配列は記述子を使用しません。一方,配列ポインタと割付け配列は,引数として使われるかどうかにかかわらず記述子を使用します。

Visual Fortran と Fortran 以外の言語 (C など) の間で呼び出しを行う場合,暗黙のインタフェースを使用すれば,配列を Visual Fortran 記述子なしで渡すことができます (「配列引数の効率的な渡し方」を参照)。ただし,呼び出されるルーチンが Visual Fortran 記述子に含まれる情報を必要とする場合,ルーチンを明示的なインタフェースを付けて宣言し,仮配列を形状引継ぎ配列として,またはポインタ属性を付けて指定します。

Fortran 95/90 ポインタは,(配列境界が「矩形」である限り) 任意の形に編成された任意のメモリー部分と関連付けることができます。また,Fortran 95/90 ポインタを C などの他の言語に渡し,その言語で記述子を正しく解釈して,必要な情報を取得することができます。

ただし,配列記述子を使用すると,エラーが起こる可能性が高まりますし,可搬性も損なわれます。

次に,Visual Fortran の配列記述子の構成要素を示します。

次元数 1 の配列では 3 つのロングワードが追加で必要となるので,合計で 8 つのロングワード (5 + 3 * 1) が含まれ,バイト 31 で終わることになります。次元数 7 の配列には,合計で 26 のロングワード (5 + 3 * 7) が含まれ,バイト 103 で終わることになります。

例として,次の宣言を考えます。

	integer,target :: a(10,10)
	integer,pointer :: p(:,:)
	p => a(9:1:-2,1:9:3)
	call f(p)
	.
	.
	.

実引数 p の記述子は,次の値を含むことになります。

各種の型の配列引数を渡すときの性能に対する影響については,「配列引数の効率的な渡し方」を参照してください。