配列を初期化するための次のプログラムについて見てみましょう。
winter: proc;
dcl n pic'99';
dcl a(0:99) fixed bin ext;
do n = 0 to 99;
a(n) = n;
end;
end;
このコードは有効な PL/I ではありません。その理由は、SIZE 条件が 有効になっている場合は、n の値が 99 になった後に SIZE 条件が 発生するからです (想定される次の値 100 は PIC'99' 変数にとって大 きすぎるため)。
最適なパフォーマンスを得るためには、ループ制御変数として PICTURE 変 数を使用することは通常、適切ではありません。しかし、上記のコードの場合は、 新しいコンパイラーによって、このループを無限に実行させるコードが生成さ れるため、PICTURE 変数を使用することは非常に不適切なことです。
DO ステートメントの定義上、上記のループは、新旧コンパイラーの どちらでも無限ループを発生させる次のコードと同じ意味です。
n = 0;
if n > 99 then go to loop_exit;
loop_body:;
a(n) = n;
n = n + 1;
if n <= 99 then go to loop_body;
loop_exit:;
ただし、DO ループを使用している元のコードの場合、従来のコンパイラー では、不正な方法により、厳密には間違っているコードが生成されます。
新しいコンパイラーでは、次のメッセージが発行されて、ユーザーにこの状 況についての警報が出されます。
IBM1089I W Control variable in DO loop cannot
exceed TO value, and loop may be infinite.
IBM1220I W Result of comparison is always constant.
IBM1220I W Result of comparison is always constant.
コンパイラーにメッセージ IBM1089 を発行させるコードがある場合は、この コードを詳しく調べる必要があります (場合によっては変更します)。 また、EXIT オプションを使用して、このメッセージの重大度を上げる こともできます。
コードを修正する場合は、DO ループ制御変数の属性を PICTURE から FIXED BIN(31) に変更します。
最後に、この問題は、DO ループ制御変数が PICTURE'(n)9' であり、n が偶数でループ制限が 10**n-1 であるいずれのループでも発生するた め注意してください。
またこの問題は、コンパイラーによってフラグが立てられていない形で生じる可能性があります。 例えば、配列を初期化するための以下のプログラムについて見てみましょう。
sommer: proc;
dcl n pic'999';
dcl a(0:999) fixed bin ext;
do n = 0 to 998 by 2;
a(n) = n;
end;
end;
この場合、TO の値 998 は n が想定する最大値よりも小さいため、コンパイラーはメッセージ IBM1089 を発行しません。 しかし n が値 998 を想定した後にループを次に通る際、n には値 0 が割り当てられ、ループが繰り返されます。
またこの問題は、BY 値が負であるときにも生じ得ます。
eiki: proc;
dcl n pic'999';
dcl a(0:99) fixed bin ext;
do n = 79 to 1 by -2;
a(n) = n;
end;
end;
しかし n が値 1 を想定した後、次にループを通る際、 n は 2 減少して値 1 が割り当てられてループが繰り返されます。