0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

FORTH ベーシックマスター Lev 11 ー CREATEとメモリ操作 ― 配列を自作する

0
Last updated at Posted at 2025-12-07

FORTHの強みの一つは、メモリ領域を直接操作できる という点にある。他の言語では「配列」や「構造体」はあらかじめ用意された抽象概念であるが、FORTHではそれらを明示的に自作 する。この「データを置く場所を自分で決める」自由こそ、FORTHの低レベル言語としての魅力であり、同時に「思考を構造化する力」を鍛える最良の教材でもある。

メモリ確保の基本 ― CREATEALLOT

FORTHにおけるCREATEは、「新しいワードを辞書に登録し、そのワードが指すメモリアドレスを用意する」命令である。

CREATE BUF

これにより、BUFという名前のワードが辞書に登録される。この時点で、BUFメモリアドレスを返すワード として定義される。

入力
BUF .S
出力例
<1> 1904232

つまり、BUFを実行すると、そのメモリ位置(アドレス)がスタックに積まれる。このアドレスは、まだ何も使われていない“空の領域”である。

次に、ALLOTを使ってこの領域に一定のバイト数を確保する。

CREATE BUF 100 ALLOT

これで、BUFは100バイト分の領域を持つデータブロックを指すようになる。FORTHでは、配列も構造体もこの仕組みから構築される。

ALLOT とは、「割り当てる」という意味の英単語。

メモリへの格納と取得 ― !@

確保した領域にデータを書き込むには、!(ストア)を使う。逆に読み出すには、@(フェッチ)を使う。

単一セルの書き込みと読み出し
VARIABLE X
123 X !
X @ .
出力
123

このVARIABLEも、内部的にはCREATEALLOTで実装されている。

: VARIABLE ( "name" -- )
  CREATE 1 CELLS ALLOT ;

配列を自作する ― CELLSとインデックス計算

FORTHでは、メモリ単位が明確である。1セル=通常は32ビットまたは64ビット(環境依存)であり、整数型データの格納にはCELLSを使うと安全である。

以下のようにして、10個の整数を格納できる配列を作ることができる。

CREATE ARR 10 CELLS ALLOT

これで、ARRは10セル分(整数10個分)の配列として機能する。各要素へのアクセスは、インデックスに応じてセル単位でアドレスを進める。

3番目の要素に値を格納
30 2 CELLS ARR + !

ここでの動作

スタック操作 意味
2 CELLS 配列内の2番目(0始まり)をセル単位でオフセット計算
ARR + ARRの基点アドレスにオフセットを足す
! そのアドレスに値を格納
読み出し
ARR 2 CELLS + @ .
出力
30

FORTHでは配列演算すら、単純なアドレス算術の組み合わせで行う。

配列アクセスワードを定義する

FORTHの真骨頂は、これらの操作を「ワード化」して再利用できる点にある。配列アクセス専用のワードを定義してみよう。

: ARR! ( n i -- )
  CELLS ARR + ! ;

: ARR@ ( i -- n )
  CELLS ARR + @ ;

これで次のように使える:

入力
10 0 ARR!
20 1 ARR!
30 2 ARR!
2 ARR@ .
出力
30

つまり、C言語で言えば ARR[2] = 30; に相当する処理をFORTHで自作したことになる。このように、FORTHでは「必要な構造はすべて自分で定義できる」。

配列の中身を表示する

FORTHにはCのようなprint_array()という命令はないが、@(読み出し)とループ構文(DO … LOOP)を組み合わせることで、簡単に配列の中身を確認できる。

配列の先頭からn個の要素を表示する
: SHOW-ARRAY ( addr count -- )
  0 DO
    CR I . ." : "          \ 改行してインデックス表示
    I CELLS OVER + @ .     \ addr[i] を表示
  LOOP
  DROP ;                    \ addrを最後に消す
実行例
ARR 3 SHOW-ARRAY
出力
0 : 10
1 : 20
2 : 30

動作

  1. スタックに ( addr count ) がある
  2. 0 DO … LOOP で I がインデックスを生成
  3. I CELLS OVER + で addr + i*cell
  4. @ で値を取り出し、. で表示
  5. 最後に OVERで残したaddrをDROPで消す

CREATE ... DOES>による“配列ワードの自動化”

ここまででARRのような単一配列を作ったが、複数の配列を動的に生成したい場合は、CREATE ... DOES>を使うのが便利である。

構文
: <定義名>
  CREATE (定義時の動作)
  DOES> (実行時の動作)
;

これにより、**「データを持ち、実行時に固有の動作をするワード」**を作れる。いわば、FORTH流の“クラスとインスタンス”のようなものだ。

: ARRAY: ( n -- )
  CREATE CELLS ALLOT
  DOES> ( i -- addr )
    SWAP CELLS + ;

このARRAY:を使うと、任意のサイズの配列をワードひとつで作れる。

10 ARRAY: DATA

これでDATAは、要素数10の配列として振る舞う。アクセスは次のように行う。

100 0 DATA !         \ DATA[0] = 100
200 1 DATA !         \ DATA[1] = 200
0 DATA @ .           \ → 100
1 DATA @ .           \ → 200

DOES>部のCELLS +が、アクセス時のアドレス計算を自動で行っている。このようにFORTHでは、言語構文を自分で定義することができる。

応用 ― 配列の初期化と走査

配列を初期化したいときも、FORTHではループを組み合わせるだけで良い。

: INIT-DATA ( n -- )
  0 DO
    I I DATA !
  LOOP ;
実行
10 INIT-DATA

これで DATA[0]=0, DATA[1]=1, … DATA[9]=9 が格納される。
確認は:

10 0 DO I DATA @ . LOOP
出力
0 1 2 3 4 5 6 7 8 9

FORTHでは、このような「低レベルなループとアドレス演算の組み合わせ」によって、高度なデータ操作がシンプルに表現できる。

メモリとFORTH哲学 ― 「データは場所で考える」

FORTHのデータ構造思想は、「データ=名前ではなく、場所(アドレス) である」という前提に立っている。この考え方は、一見古風に見えるが、制御系や科学計算の世界では今も生きている。センサー値を連続的に記録する配列、シミュレーションの状態変数を保持するテーブルなど、FORTHの“場所志向の設計”は極めて直感的で、効率がよい。

この「自分で作る配列」は、次回のDOES>によるオブジェクト的構造の設計、さらには行列演算・科学データ処理への基盤となる。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?