PROC FCMPの初期化されていない変数は、デフォルトの長さ33バイトを取得しているようです。次のデモコードを検討してください。
OPTIONS INSERT = (CMPLIB = WORK.FCMP);
PROC FCMP
OUTLIB = WORK.FCMP.FOO
;
FUNCTION FOO(
BAR $
);
* Assign the value of BAR to the uninitialised variable BAZ;
BAZ = BAR;
* Diagnostics;
PUT 'BAR IS ' BAR;
PUT 'BAZ IS ' BAZ;
* Return error code;
IF
LENGTH(BAZ) NE LENGTH(BAR)
THEN
RETURN(0)
; ELSE
RETURN(1)
;
ENDSUB;
RUN;
DATA _NULL_;
X = 'shortstring';
Y = 'exactly 33 characters long string';
Z = 'this string is somewhat longer than 33 characters';
ARRAY STRINGS{*} _CHARACTER_;
ARRAY RC{3} 8 _TEMPORARY_;
DO I = 1 TO DIM(STRINGS);
RC[I] = FOO(STRINGS[I]);
END;
RUN;
これは、私のサイトのインストール(Base SAS 9.4 M2)で、次の行をログに出力します。
BAR IS shortstring
BAZ IS shortstring
BAR IS exactly 33 characters long string
BAZ IS exactly 33 characters long string
BAR IS this string is somewhat longer than 33 characters
BAZ IS this string is somewhat longer th
これは、DATAステップと同様に、PROCFCMPが実行時に可変長を動的に割り当てることができないという事実に関連している可能性があります。ただし、パラメータに可変長を動的に割り当てるため、少し混乱します。PROC FCMPサブルーチンには別の「初期化」フェーズがあり、その間に引数として渡される値の長さが決定され、それらの値を保持する必要のあるパラメーター変数が必要な長さに初期化されると想定しています。ただし、定義された変数の長さのみサブルーチンの本体内は、メモリがすでに割り当てられている実行時にのみ検出できます。したがって、実行前(コンパイル時または仮想の「初期化」フェーズ)に、メモリは明示的なLENGTHステートメントが存在する場合はこれらの変数に割り当てられ、それ以外の場合はデフォルトの33バイトにフォールバックします。
ここで本当に興味深いのは、PROC FCMPが、初期化/実行時の段階を厳密に分離した範囲内で、これについて可能な限り賢いことです。サブルーチンの本体で、変数に明示的に定義されたLENGTHがあり、次にA
別の初期化されていない変数B
に関数が割り当てられている場合、はと同じ長さに設定されます。上記の関数のこの変更について考えてみます。ここでは、の値がに直接割り当てられるのではなく、明示的に50バイトが定義されている3番目の変数を介して割り当てられます。A
B
A
BAR
BAZ
QUX
LENGTH
OPTIONS INSERT = (CMPLIB = WORK.FCMP);
PROC FCMP
OUTLIB = WORK.FCMP.FOO
;
FUNCTION FOO(
BAR $
);
LENGTH QUX $ 50;
QUX = BAR;
* Assign the value of BAR to the uninitialised variable BAZ;
BAZ = QUX;
* Diagnostics;
PUT 'BAR IS ' BAR;
PUT 'BAZ IS ' BAZ;
* Return error code;
IF
LENGTH(BAZ) NE LENGTH(BAR)
THEN
RETURN(0)
; ELSE
RETURN(1)
;
ENDSUB;
RUN;
DATA _NULL_;
X = 'shortstring';
Y = 'exactly 33 characters long string';
Z = 'this string is somewhat longer than 33 characters';
ARRAY STRINGS{*} _CHARACTER_;
ARRAY RC{3} 8 _TEMPORARY_;
DO I = 1 TO DIM(STRINGS);
RC[I] = FOO(STRINGS[I]);
END;
RUN;
ログは次のことを示しています。
BAR IS shortstring
BAZ IS shortstring
BAR IS exactly 33 characters long string
BAZ IS exactly 33 characters long string
BAR IS this string is somewhat longer than 33 characters
BAZ IS this string is somewhat longer than 33 characters
この「役立つ」行動が、以前の回答との混乱や違いの原因である可能性があります。この動作が文書化されているのだろうか?
スマートSASがこれをどのように実現しようとしているのかを正確に調査するための演習として、読者に任せます。たとえば、初期化されていない変数に、明示的に割り当てられた長さを持つ他の2つの変数の連結値が割り当てられた場合、その長さは他の2つの変数の合計に設定されますか?