先の章でポインターとはフィールドの開始位置として捉えればよい、ということまでは理解されたと思う。
またポインター自身も 16バイトの変数であることも学習した。
次に具体的にポインターを扱う方法を紹介する。
まず、ポインターのタイプの型であるが、つまり英字フィールドであれば A で
ゾーン10進数であれば S で表すところ、ポインターは * で表す。
D DSPRCD S 10A D DSPRCDA S 11A D DSPRCD_P S * D NULL S 1A INZ(X'00')
この D-仕様書での定義ではレコード名が保存される DSPRCD
という名前のフィールドに対して
11 桁の DSPRCDA
という名前のフィールドを定義している。
さらにタイプを * で定義されている DSPRCD_P
がポインターである。
まず最初の使い方として
C DSPRCD CAT NULL:0 DSPRCDA C EVAL DSPRCD_P = %ADDR(DSPRCDA)
のように演算する。
DSPRCDA
が 11桁として定義されていたのは
C DSPRCD CAT NULL:0 DSPRCDA
のようにして DSPRCD
と NULL
(ヌル値 X'00') とを結合して DSPRCDA
を作るためである。
そうやって DSPRCD
の値の最後に NULL
を付加した DSPRCDA
に対して、初めて
C EVAL DSPRCD_P = %ADDR(DSPRCDA)
のようにして %ADDR
によってポインター DSPRCD_P
を算出している。
このように文字列の最後に NULL
を付加したものを指すポインターを定義することは、
C言語では一般的でよく使う。
このことを NULL-STOP と呼ぶ。
変数の型としてポインターを扱うとポインターは、先にも解説したように変数の開始位置であるので
開始位置だけでは、その変数はどの位置まで定義されているのか把握することができない。
このため終わりの位置を示すために NULL
を付加して終わりを示すのである。
文字列+NULL
を示す型は C言語では
CHAR*
と表現される。( * とはポインターの意味 )
この CHAR*
(または char*
) は非常に頻繁に使用される型であり i5/OS の API でも char*
として
定義されている変数は、ごく普通に見られるので NULL
を付加してからポインターを定義する、と
いう方法を良く覚えていて欲しい。
さてこのように NULL-STOP によって変数の長さがわかるように定義するのが char*
であるなら
char*
は動的な長さを定義するのにもってこいであるし、任意の長さの文字変数を定義できるのでは
ないかと思われた方もいると思うが、まさしくそのとおりである。
char*
を受け取る側の API は任意の長さの変数を受け取って処理することができる。
API は汎用的に使用されることを目的としているために char*
を受け取りパラメータの変数に
していることが多いのである。
従って RPG 側でもポインターを定義する必要性がある。
NULL-STOP をつけないでポインターだけを API に渡すと API は NULL
が見つかるまで
その変数の長さがあるものと誤解して、莫大な長さと解釈してしまう。
場合によってはメモリ・エラーを引き起こしてしまうので必ず NULL-STOP をつけるように注意されたい。
本章で学んだのは
%ADDR
を使うとポインターを定義することができる