%ADDR (変数のアドレスの検索)

%ADDR(variable)
%ADDR(varying-length variable : *DATA)

%ADDR は基底ポインター・タイプの値を戻します。 この値は、指定された変数のアドレスです。 この値は基底ポインター・タイプの項目とだけ比較することができ、基底ポイン ター・タイプの項目にだけ割り当てることができます。

%ADDR は、2 番目のパラメーターとして *DATA が指定されている場合に、可変長フィールドのデータ部を戻します。

配列指標パラメーターを持つ %ADDR が定義仕様書のキーワード INZ または CONST のパラメーターとして指定された場合には、その配列指標がコンパイル時 に分かっていなければなりません。指標は数値リテラルか数値定数のいずれかでなければなりません。

割り当ての結果が指標を持たない配列となる EVAL 命令では、割り当て演算子の右辺 の %ADDR は %ADDR の引数によって異なる意味を持ちます。 %ADDR の引数が指標 の指定がない配列名で、結果が配列名となる場合には、結果の配列の各要素には 引数の配列の先頭のアドレスが入れられることになります。 %ADDR の引数が (*) の指標を指定した配列名である場合には、結果の配列の各要 素には引数の配列の対応する要素のアドレスが入れられることになります。 これは 図 1 に例示されています。

パラメーターとして指定された変数がテーブル、複数オカレンス・データ構造、または複数オカレンス・データ構造のサブフィールドである場合には、アドレスは現在のテーブル の指標または繰り返し番号になります。

変数が基底付きである場合には、%ADDR はその変数の基底ポインターの値を戻し てきます。 変数が基底付きデータ構造のサブフィールドである場合には、%ADDR の値は基底 ポインターにサブフィールドのオフセットを加えた値になります。

変数が *ENTRY PLIST の PARM として指定された場合には、%ADDR は呼び出し元に よってプログラムに渡されたアドレスを戻してきます。

%ADDR の引数を変更することができない場合、%ADDR は比較演算でのみ使用することができます。 変更できない引数の例として、読み取り専用参照パラメーター (プロシージャー・インターフェース で指定された CONST キーワード) があります。

図 1. %ADDR の例
 *..1....+....2....+....3....+....4....+....5....+....6....+....7...+....
D*Name++++++++++ETDsFrom+++To/L+++IDc.Keywords+++++++++++++++++++++++++
 *
 * The following set of definitions is valid since the array
 * index has a compile-time value
 *
D   ARRAY         S             20A   DIM (100)
 * Set the pointer to the address of the seventh element of the array.
D   PTR           S               *   INZ (%ADDR(ARRAY(SEVEN)))
D   SEVEN         C                   CONST (7)
 *
D DS1             DS                  OCCURS (100)D                               20A
D   SUBF                        10A
D                               30A
D CHAR10          S             10A   BASED (P)
D PARRAY          S               *   DIM(100)


  /FREE
    %OCCUR(DS1) = 23;
    SUBF = *ALL'abcd';
    P = %ADDR (SUBF);
    IF CHAR10 = SUBF;
       // This condition is true.
    ENDIF;
    IF %ADDR (CHAR10) = %ADDR (SUBF);
       // This condition is also true.
    ENDIF;
    // The following statement also changes the value of SUBF.
    CHAR10 = *ALL'efgh';
    IF CHAR10 = SUBF;
       // This condition is still true.
    ENDIF;
    //--------------------------------------------------------------
    %OCCUR(DS1) = 24;
    IF CHAR10 = SUBF;
      // This condition is no longer true.
    ENDIF;
    //--------------------------------------------------------------
    // The address of an array element is taken using an expression
    // as the array index.
    P = %ADDR (ARRAY (X + 10));
    //--------------------------------------------------------------
    // Each element of the array PARRAY contains the address of the
    // first element of the array ARRAY.
    PARRAY = %ADDR(ARRAY);
    // Each element of the array PARRAY contains the address of the
    // corresponding element of the array ARRAY.
    PARRAY = %ADDR(ARRAY(*));

    // The first three elements of the array PARRAY
    // contain the addresses of the first three elements
    // of the array ARRAY.
    %SUBARR(PARRAY : 1 : 3) = %ADDR(ARRAY(*));
  /END-FREE     
図 2. *DATA が指定されている %ADDR の例
1. Use %ADDR(fld:*DATA) to call a procedure with the
   address of the data portion of a varying field.

// Assume procedure "uppercaseData" requires a pointer and a length.
// %ADDR(fld:*DATA) returns the pointer to the data portion of
// the varying field, and %LEN(fld) returns the length.
uppercaseData (%ADDR(fld : *DATA) : %LEN(fld));

2. Use %ADDR(fld:*DATA) to determine the maximum size
   of the data portion of a varying field.

// The number of bytes used for the prefix is the
// offset between the address of the field and the
// address of the data.
prefix_size = %addr(fld : *data) - %addr(fld);

// The number of bytes used for the data is the
// difference between the total bytes and the
// bytes used for the prefix.
data_size = %size(fld) - prefix_size;

// If variable "fld" is UCS-2 or DBCS, the number
// of characters is half the number of bytes
max_dbcs_chars = data_size / 2;