1. 導入:なぜポインタの「逆算」が重要なのか
メインフレーム開発、特にPL/Iやアセンブラを用いた低レイヤの処理において、ポインタ操作は避けて通れません。通常はアドレスを「加算」してデータ構造内を進みますが、構造体の末尾からヘッダー情報へアクセスしたり、スタック領域を末尾から先頭へスキャンしたりする場面では、アドレスを「差し引く」操作が不可欠です。本稿では、PTRADD組み込み関数を用いた「負のオフセット」演算について解説します。
2. 基礎知識:ポインタとロケータの概念
メインフレーム環境におけるポインタは、メモリ上の物理的なアドレスを直接指し示すものです。
ポインタ:メモリ上の特定のアドレス値そのものを保持する変数。
ロケータ:PL/Iなどで使われる、データのアドレスを修飾・特定するための仕組み。
PTRADD関数は、基準となるポインタに対して指定バイト数を加減算し、新しいアドレスを返します。通常はプラスの値を指定しますが、負の値を指定することで「メモリを逆方向に辿る」ことが可能になります。
3. 実装・解決策
PTRADD(P, N)において、第2引数に負の整数を指定します。これにより、現在の位置からメモリの下位アドレス(開始側)へポインタを移動させることができます。重要なのは、計算結果が意図したデータ領域の境界内に収まっているかを確認することです。
4. サンプルプログラム
以下は、バッファの末尾からヘッダーサイズ分だけ戻り、先頭アドレスを取得する例です。
/ PL/I サンプルコード /
DCL P_END PTR; / バッファの末尾ポインタ /
DCL P_START PTR; / 計算後の開始ポインタ /
DCL BUFFER_LEN FIXED BIN(31) INIT(1024); / バッファ全体のサイズ /
/ P_ENDから1024バイト戻った位置をP_STARTとする /
P_START = PTRADD(P_END, -BUFFER_LEN);
/ 動作確認用のコメント:これでバッファの先頭を指すポインタが生成された /
/ この後、P_STARTをベースに構造体のマッピングを行う /
5. 応用・注意点
この操作には、現代の言語にはないメインフレーム特有の注意点があります。
保護例外(Protection Exception)への警戒:
物理アドレスを直接操作するため、計算結果が割り当てられたメモリ領域(ページ境界)を越えてしまうと、OSによって即座に保護例外が発生し、プログラムがアベンドします。
インデックス計算の正当性確認:
負のオフセットを使用する際は、必ず計算前に「現在の位置」と「引きたいサイズ」を検証してください。特にループ処理内でPTRADDを使用する場合、カウンターの誤りにより意図せず保護領域までポインタが移動してしまうバグが最も一般的です。コードレビュー時は、減算後のアドレスが期待するデータ構造の開始位置と一致しているか、境界チェック(Bound Check)を怠らないようにしましょう。

コメント