Next: , Previous: , Up: Structures   [Contents][Index]


6.23.2 Structure Usage

以下のコマンドを使用して、 (データのない)リンク・リストの構造体を定義できます(訳注: これは構造体テンプレートを定義するだけです。 構造体変数とするには別途 %alloc 等する必要があります):

struct
    cell% field list-next
end-struct list%

スタック上のリスト・ノードのアドレスを使用して、 list-next を使用して次のノードのアドレスを含むフィールドのアドレスを計算できます。 たとえば、 以下のようにしてリストの長さを決定できます:

: list-length ( list -- n )
\ "list" is a pointer to the first element of a linked list
\ "n" is the length of the list
    0 BEGIN ( list1 n1 )
        over
    WHILE ( list1 n1 )
        1+ swap list-next @ swap
    REPEAT
    nip ;

list% %allot を使用すると、 ディクショナリ内にリスト・ノード用のメモリを確保でき、 これにより、 リスト・ノードのアドレスがスタック上に残ります。ヒープ上で同様の割り当てを行うには、 list% %alloc を使用できます(または、allocate のようなスタック効果(つまり、ior を使用)が欲しい場合は、 list% %allocate を使用します)。 リスト・ノードのサイズは list% %size で取得でき、 そのセル・アライメントは list% %alignment で取得できます。

注意: 標準 Forth では、 create されたワードの本体は aligned されていますが、 必ずしも faligned されている訳ではない事に注意してください。したがって、 以下のようにすると:

create "name" foo% %allot drop

この場合、 foo% に割り当てられたメモリは、 foo% に文字フィールドやセル・フィールドや2倍長整数フィールドのみが含まれている場合にのみ、 name の本体から開始されることが保証されます。 したがって、 浮動小数点数が含まれる場合は、以下を使用することをお勧めします

foo% %allot constant "name"

以下のように、 構造体 foo% を別の構造体のフィールドとして含めることができます:

struct
...
    foo% field ...
...
end-struct ...

構造体をいちから構築する代わりに、 既存の構造体を拡張できます。 たとえば、 上記例で定義したような、 データのない単純なリンク・リストはほとんど役に立ちません。 これを以下のように、 整数の値を持つリンク・リストに拡張できます:31

list%
    cell% field intlist-int
end-struct intlist%

intlist% は、 list-nextintlist-int の 2 つのフィールドを持つ構造体です。

以下のように、 n 要素の foo% 型を含む配列型を指定できます:

foo% n *

この配列型は、 通常の型を使用できる場所であればどこでも使用できます(例: field を定義する場所や %allot を使用するとき)。

最初のフィールドは構造体のベース・アドレスにあり、 この、 最初のフィールドのワード(例: list-next)は実際にはスタック上のアドレスを変更しません。 あなたは実行時間と領域の効率を考慮して、 最初のフィールドのワードを取り除きたいとと思うかもしれません。 しかし、 構造体パッケージがこの場合を最適化するため、 そのは必要ありません。 最初のフィールドのワードをコンパイルする場合、 コードは生成されません。 したがって、 読みやすさと保守性を考慮して、 最初のフィールドにアクセスするときにその最初のフィールドのワードは含めるべきです。


Footnotes

(31)

この機能は「拡張レコード」(extended records)とも呼ばれます。 これは、 オベロン・プログラミング言語が成した主な革新です。 言い換えれば、 この機能を Modula-2 に追加することで、 Wirth は新しい言語を作成し、 新しいコンパイラの記述等を行いました。 この機能を Forth に追加するには、 数行のコードが必要なだけでした。