複数のフィールドを含む構造体を使用したい場合は、 その構造体用にメモリーを予約し、 アドレス算術演算を使用してフィールドにアクセスするだけです(see Address arithmetic)。 例として、 以下の 3 つのフィールド(a, b, c)を持つ構造体を考えてみましょう
a
これは浮動小数点数(float)です
b
これはセル(cell)です
c
これは浮動小数点数(float)です
構造体の (float 整列された) ベース・アドレスが与えられると、
a
それ以上何もせずに a フィールドが得られます。
b
float+
すると b フィールドが得られます。
c
float+ cell+ faligned
すると c フィールドが得られます。
これが非常に疲れる可能性があることは容易にわかります。
さらに加えて、 cell+
を見ても、 どの構造体がアクセスされているか、 どのフィールドがアクセスされているかがわからないため、
あまり読みやすくありません。 何らかの方法で構造体の種類を推測し、
その構造体のどのフィールドがそのオフセットに対応するかをドキュメントで調べる必要があります。
最後に、 この種のアドレス計算はメンテナンスの問題も引き起こします。 構造体の途中にフィールドを追加・削除した場合、 その後フィールドのすべてのアドレス計算を探し出して変更する必要があります。
そこで、 cell+
とそのファミリーを直接使用する代わりに、 以下のようにオフセットを定数に保存してはどうでしょうか?:
0 constant a-offset 0 float+ constant b-offset 0 float+ cell+ faligned c-offset
これで、 x-offset +
を使用してフィールド x
のアドレスを取得できるようになりました。
これはあらゆる点ではるかに優れています。 もちろん、 フィールドを追加する場合は、 その後のオフセット定義をすべて変更する必要があります。 これは、
以下の方法でオフセットを宣言することで改良できます:
0 constant a-offset a-offset float+ constant b-offset b-offset cell+ faligned constant c-offset
オフセット計算にはいつも +
を使うので、 定義されたワードのアクションに +
を含む定義ワード cfield
を使用できます:
: cfield ( n "name" -- ) create , does> ( name execution: addr1 -- addr2 ) @ + ; 0 cfield a 0 a float+ cfield b 0 b cell+ faligned cfield c
今や、 x-offset +
の代わりに、 単に x
と書くことができるようになりました。
構造体フィールドのワード群が非常にうまく使用できるようになりました。 ただし、 その定義はまだ少し面倒です。 名前を繰り返す必要があり、 サイズと配置に関する情報はフィールド定義の前後に配置されます。 このセクションで紹介する構造体パッケージは、 これらの問題に対処します。