C では、構造体の中に、別の構造体へのポインタを入れることがよくあります。プリミティブ xdr_reference() を使用すると、そのように参照される構造体を簡単にシリアライズ (またはデシリアライズ) できます。
bool_t xdr_reference(xdrs, pp, size, proc) XDR *xdrs; char **pp; u_int ssize; bool_t (*proc)(); |
引数 pp は構造体へのポインタのアドレスです。引数 ssize は構造体のサイズ (バイト数) です。C の sizeof() 関数を使用してこの値を調べることができます。引数 proc() は構造体を記述する XDR ルーチンです。データを復号化するとき、*pp が NULL の場合は記憶領域が割り当てられます。
プリミティブ xdr_struct() では、構造体内の構造体を記述する必要はありません。ポインタだけで十分です。
xdr_array() を使用して xdr_reference() を作成してください。
xdr_reference() と xdr_array() のデータ外部表現は互換ではありません。
人の名前、および、その人の総資産と負債の入った gnumbers 構造体へのポインタとで構成される次のような構造体があるとします。
struct pgn { char *name; struct gnumbers *gnp; }; |
これに対する XDR ルーチンは次のようになります。
bool_t xdr_pgn(xdrs, pp) XDR *xdrs; struct pgn *pp; { return(xdr_string(xdrs, &pp->name, NLEN) && xdr_reference(xdrs, &pp->gnp, sizeof(struct gnumbers), xdr_gnumbers)); } |
C のプログラマは多くのアプリケーションで、ポインタの値に 2 つの意味を持たせています。一番多い例としては、ポインタ値が NULL (ゼロ) の場合はデータが不要なことを意味する方法ですが、アプリケーションごとにさまざまな解釈ができます。実際に C プログラマは、ポインタ値の解釈をオーバロードすることにより、効率よく識別型共用体を実現しています。たとえば、サンプルプログラム E では、gnp のポインタ値を NULL にすれば、その人の総資産と負債が未知であると解釈できます。すなわち、ポインタ値には 2 つの意味があります。データがあるかどうかを示し、もしあるとしたらメモリーのどこにあるかを示します。リンクリストは、アプリケーション固有のポインタ解釈の極端な例です。
プリミティブ xdr_reference() はシリアライズの際に、値が NULL のポインタに特別な意味を持たせることができません。そのため、データをシリアライズするときに、xdr_reference() に値が NULL のポインタのアドレスを渡すと、多くの場合メモリーフォルトを引き起こし、UNIX システムではコアダンプが起こります。