ロケーター・データには 2 つのタイプ、ポインターとオフセットがあります。
ポインター変数 の値は、ストレージの位置のアドレスです。 いくつかの異なる記憶場所でストレージを割り振られた変数を参照するときは、この値を使って参照を修飾することができます。
オフセット変数 の値は、区域変数内の位置を指定し、その区域がストレージの別の場所に割り当てられている場合には引き続き有効です。
ロケーター値は、ロケーター変数にだけ割り当てることができます。 オフセット値がオフセット変数に割り当てられるときは、OFFSET 属性で 指定された区域変数は無視されます。
ロケーター・データをほかのデータ・タイプに変換することはできません。 ただし、次の場合は変換することができます。
オフセット変数が参照されると、OFFSET 属性およびオフセット変数で指定され た区域変数のアドレスによって、オフセット変数はポインター値に暗黙に変換 されます。 POINTER 組み込み関数を使用すれば、オフセットをポインター値に明示的に変換することができます。 次の例では、ステートメントは、区域 B 内のオフセット O に よって識別される基底付き変数の記憶位置を示すポインター値 を、P に割り当てます。
dcl P pointer, O offset(A),B area; P = pointer(O,B);
この区域変数は、オフセット変数に関連付けられた区域変数とは異なっているので、そのオフセット値が別の区域で有効であるかを確認しなければなりません。 例えば、区域 A が区域 B に割り当てられたあとでこの 関数が呼び出された場合は、そのオフセット値は有効です。
OFFSET 組み込み関数は、POINTER 組み込み関数とは対照的に、与えられたポインター と区域から得られたオフセット値を返します。 この場合、そのポインター値は、その区域内での基底付き変数の位置を 示していなければなりません。
ポインター値は、そのポインター値およびその区域のアドレスを使用して、オフセットに変換されます。 したがって、この変換ができるのは、OFFSET 属性内で指定された区域内のアドレスに結び付けられたポインター値に限られます。
NULL 組み込み関数または SYSNULL 組み込み関数の値に割り当てる場合を除いて、区域 に関連付けられていないオフセット変数への変換や、このオフセット変数から の変換を試みると、エラーになります。
複数割り当ての場合、ロケーターは暗黙に変換されることはありません。
ロケーター参照とは、ロケーター変数 (修飾付きまたは添え字付きでもよい) また は、ロケーター値を返す関数参照のいずれかのことです。
ロケーター参照は、次のように使用することができます。
PL/I はオフセットをポインター値に暗黙に変換するため、 オフセット参照とポインター参照のどちらも使用することができます。
ロケーター修飾とは、ロケーター基底付き変数の特定の世代を識別するために、1 つ以上のロケーター参照を基底付き参照に関連付けることです。 これを、ロケーターで修飾された参照といいます。 複合記号 -> は、「〜で修飾された」または「〜を指す」という意味を 表します。 明示的に修飾された参照の構文図を次に示します。
次の例では、X は基底付き変数であり、P はロケーター 変数であり、Q は基底付きロケーター変数です。
P -> Q -> X
この参照は、 基底付きロケーター Q、 およびロケーター P の値によって 識別される X の世代を意味しています。 X と Q は、明示的にロケーター修飾されている といいます。
複数のロケーター修飾子を使用している場合、それらの値の計算は順に左から右へ行われます。
基底付き変数の参照を暗黙に修飾する こともできます。 暗黙に修飾された基底付き変数の世代を判別するために使われるロケーター参照は、基底付き変数と一緒に宣言されたものです。 次の例では、ALLOCATE ステートメントは、ポインター変数 P の値を セットします。したがって、X を参照すると、割り振られたストレージ が参照されます。
dcl X fixed bin based(P) init(0); allocate X; X = X + 1;
代入ステートメントで X を参照していますが、これは P によって暗黙にロケーターで修飾されます。 X を参照するとき、次の例のように明示的にロケーターで修飾することもできます。
P->X = P->X + 1;
次の代入ステートメントが実行されると、 上記の場合と同じ結果になります。
Q = P; Q->X = Q->X + 1;
基底付き変数と一緒に宣言されるロケーターも基底付きであってもかまいま せん。したがって、ロケーター修飾子のチェーンになることがあります。 例えば、 次のようなポインターおよび基底付き変数を使用することができます。
declare (P(10),Q) pointer,
R pointer based (Q),
V based (P(3)),
W based (R),
Y based;
allocate R,V,W;
先のように宣言し、割り振りを行った場合、 下記の参照はすべて正しい参照です。
P(3) -> V V Q -> R -> W R -> W W
最初の 2 つの参照は同じことを意味し、その次の 3 つも同じことを意味します。 Y を参照するときは、それを修飾するロケーター変数を指定しなければなりません。
基底付き変数を修飾するポインターは、1 レベルのロケーター修飾を表します。 オフセットは、区域内で暗黙に修飾されているので、2 レベルのロケーター修飾を表します。 レベルの数は、添え字付きのロケーターであるかどうか、もしくは構造体または共用体のエレメントであるかどうかとは無関係です。 次の例では、X、P -> X、 および Q -> P -> X という参照は、 3 レベルのロケーター修飾を表しています。
declare X based (P),
P pointer based (Q),
Q offset (A);