1. 導入:なぜ「関数アドレス」を扱う必要があるのか?
メインフレームのPL/I開発において、通常のサブルーチン呼び出し(CALL文)は、コンパイル時に呼び出し先が確定する「静的な結合」です。しかし、実行時の状況に応じて呼び出す処理を切り替えたり、OSのサービスへ「この処理を実行してほしい」と通知したりする場面では、処理そのものの「場所(アドレス)」を指定する必要があります。これが「ADDR組み込み関数」を利用したポインタによる制御です。この技術を習得することで、柔軟なプログラム設計が可能になります。
2. 基礎知識:ポインタとロケータの役割
PL/Iにおけるポインタ(POINTER)とは、あるデータの場所を指し示す「住所」を格納する箱です。
通常、変数の値を扱う際には変数の名前を使いますが、アドレスを直接扱うことで、プログラムは実行中に「今はどの処理を実行すべきか」を動的に判断できるようになります。
ADDR関数は、指定したプログラム名(サブルーチンや関数)がメモリ上のどこに配置されているかという「エントリポイントのアドレス」を取得する魔法の命令です。現代のプログラミング言語にある「関数ポインタ」や「メソッド参照」と同じ概念だと理解してください。
3. 実装:ADDR関数の使い方
手順は非常にシンプルです。
1. 呼び出し先のアドレスを格納するためのポインタ変数を宣言する。
2. ADDR関数を使用して、サブルーチン名のアドレスを取得し、ポインタ変数に代入する。
3. 必要に応じて、そのポインタ変数経由でサブルーチンを呼び出す。
この仕組みにより、呼び出し先をハードコーディングせずに、変数の中身を入れ替えるだけで処理を切り替えることができます。
4. サンプルプログラム
以下のコードは、ポインタ変数を使用して動的にサブルーチンを呼び出す例です。
/ ポインタ変数の宣言 /
DCL P_FUNC POINTER;
/ 呼び出される対象のサブルーチン(外部または内部) /
SUB_PROCESS: PROCEDURE;
PUT SKIP LIST(‘サブルーチンが実行されました’);
END SUB_PROCESS;
/ メイン処理 /
MAIN: PROCEDURE OPTIONS(MAIN);
/ SUB_PROCESSのアドレスを取得し、ポインタに格納 /
P_FUNC = ADDR(SUB_PROCESS);
/ ポインタ経由でサブルーチンを呼び出す /
/ CALLの後にポインタ変数を記述することで実行可能 /
CALL P_FUNC;
END MAIN;
5. 応用・注意点:現場でのトラブルを避けるために
注意点1:インターフェースの整合性
ポインタ経由で呼び出す場合、コンパイラは呼び出し先が本当に正しい形式か(引数の型や数)をチェックしきれないことがあります。呼び出し先と呼び出し元のインターフェース定義(ENTRY宣言など)は厳密に一致させてください。
注意点2:アドレスの有効性
プログラムが終了したり、メモリからロード解除されたりした後のアドレスを保持し続けると、異常終了(ABEND)の原因となります。ポインタの有効範囲(スコープ)を正しく管理し、不要になったアドレスはNULL(ADDR(NULL))でクリアする癖をつけましょう。
注意点3:64bit環境への意識
現代のメインフレームは64bitモードが主流です。昔の31bit専用のコードをそのまま持ち込むとアドレッシングエラーになる可能性があります。コンパイルオプションで適切なアドレッシングモードを指定しているか、常に確認するようにしてください。

コメント