導入:なぜ「BYADDR」を意識する必要があるのか
メインフレームのPL/I開発において、プログラム間でデータをやり取りする際、引数の渡し方が曖昧だと「意図しない値の書き換え」という重大なバグを招くことがあります。特に、C言語やJavaのような「値渡し」に慣れた方にとって、PL/Iのデフォルト動作は少し特殊です。今回解説する「BYADDR(参照渡し)」を明示的に指定することで、プログラムの安全性を高め、メモリ破壊のリスクを未然に防ぐ方法を学びましょう。
基礎知識:引数の渡し方の基本「BYVALUE」と「BYADDR」
PL/Iでは、サブルーチンへ引数を渡す際、主に2つの方法があります。
1. BYVALUE(値渡し)
引数の「値そのもの」を渡します。コピーが渡されるため、サブルーチン内で値を書き換えても呼び出し元には影響しません。
2. BYADDR(参照渡し)
引数の「メモリアドレス」を渡します。サブルーチン内で値を変更すると、呼び出し元の変数も直接書き換わります。これを「副作用」と呼びますが、PL/Iではデフォルトでこの動作になります。
現代のプログラミングでは、どちらの方式で渡しているかをコード上で明確にすることが、保守性を高める上で非常に重要です。
実装:BYADDRの明示的な宣言
サブルーチンを定義する際、ENTRY宣言に「BYADDR」を付与することで、コンパイラと開発者の双方に対して「この引数はメモリを直接参照させる」という意図を明確に伝えます。これにより、誤ってBYVALUEとして呼び出そうとした場合にコンパイルエラーを出し、設計ミスを早期に発見できるようになります。
サンプルプログラム:BYADDRを用いた引数渡し
以下に、数値をインクリメントするシンプルなプログラム例を示します。
/ サブルーチンの宣言:BYADDRを明示 /
DCL ADD_ONE ENTRY(FIXED BIN(31) BYADDR);
/ メイン処理 /
TEST_PROC: PROC OPTIONS(MAIN);
DCL MY_VAL FIXED BIN(31) INIT(10);
PUT SKIP LIST(‘変更前: ‘ || MY_VAL);
/ サブルーチン呼び出し:MY_VALのアドレスが渡される /
CALL ADD_ONE(MY_VAL);
PUT SKIP LIST(‘変更後: ‘ || MY_VAL); / 結果は11になる /
END TEST_PROC;
/ サブルーチンの実装 /
ADD_ONE: PROC(P_VAL);
DCL P_VAL FIXED BIN(31) BYADDR; / 呼び出し元と同じメモリ領域を参照 /
P_VAL = P_VAL + 1; / ここで値を更新すると呼び出し元にも反映される /
END ADD_ONE;
応用・注意点:現場で役立つ運用テクニック
現場でレガシーコードを改修する際、既存のENTRY宣言に「BYADDR」が付いている箇所は、「値の持ち帰り」を前提とした重要なインターフェースであることを示しています。
注意点として、BYVALUEとBYADDRが混在するサブルーチンを作成する場合は、必ず全ての引数に対して属性を明示してください。一部を省略するとデフォルト属性が適用されますが、コンパイラやコンパイルオプションによって解釈が異なるリスクがあるためです。
また、意図的に値を変更させたくない引数には、BYVALUEを使用するか、読み取り専用の構造体として定義することを推奨します。「どこが書き換わる可能性があるのか」をコードから読み取れるようにしておくことが、ベテランエンジニアへの第一歩です。

コメント