我需要一个动态数组,但我不知道如何实现它。我在网上搜索了一下,也找不到任何结果。我对forth很陌生,刚刚开始学习。我想我可以使用一个变量来存储长度,并分配更多,但我不知道这是否有效,因为我也能够在数组的分配空间之外写入。
这取决于你真正需要什么。下面是创建动态单元格数组的代码。快速测试在VFX Forth和GForth。可能有更整洁更好的优化版本。
0 [IF]
dynamic array is an address stored in the dictionary pointing to
a structure stored in allocated memory
0 CELL data size in bytes n CELLS
1 CELL start of data
...
n CELL End of data
[THEN]
Take dictionary address and return addresses of the array
: array-size a -- n ;
@ @ ;
: array-data a -- a' ;
@ CELL + ;
**********************************************************
**********************************************************
Expand the data structure and copy the 'old' data into it.
This either expands the data to size or to twice the
original size whichever is larger.
ALLOCATE THROW and FREE THROW catch & report any memory
errors.
**********************************************************
: dyn-expand size a-dict -- ;
DUP >R
array-size 2* MAX new-size = largest of the ix offset
or 2 * current size.
DUP CELL + ALLOCATE THROW ( new-size new-addr )
2DUP CELL + SWAP ERASE zero the newly allocated memory
R@ array-data OVER CELL + R@ array-size
( size new-addr old-data-a new-data-a old-size )
MOVE Shift existing data to the new addr. ( size new-addr )
R@ @ FREE THROW Free the old data's memory
TUCK ! Store the new size
R> ! ; Store the new address in the dictionary
: dynamic-array CREATE: count -- ; DOES> ix -- a
Creates a dynamic array of count cells in ALLOCATED memory.
CREATE count -- ;
CELLS DUP CELL + ALLOCATE THROW ( count addr )
DUP , Store the data address in the dictionary
2DUP ! Store the data size in the allocated memory
CELL + SWAP ERASE Zero the new data region.
DOES> ix -- addr-of-ix-cell ;
Returns the address of the ix th cell. Expanding the array if required.
( ix a )
SWAP CELLS SWAP 2DUP array-size >= IF ix not in allocated range
2DUP dyn-expand
THEN
( ix-cells a ) array-data + ;
: dyn-stats. a -- ; Prints base address and array size
." Base data address: " DUP .
." Data size in bytes: " CELL - @ . ;
快速测试和使用:
16 dynamic-array ]test ok
456 0 ]test ! 4560 10 ]test ! ok
CR 0 ]test dyn-stats. ." 0th and 10th Data: " 0 ]test @ . 10 ]test @ . CR
Base data address: 9459864 Data size in bytes: 128 0th and 10th Data: 456 4560
******* ***
ok
1600 16 ]test ! This extends the array. ok
CR 0 ]test dyn-stats. ." 0th and 10th Data: " 0 ]test @ . 10 ]test @ . CR
Base data address: 10502952 Data size in bytes: 256 0th and 10th Data: 456 4560
ok ******** Address Changed *** & size changed unchanged!!
." 16th data: " 16 ]test @ . 16th data: 1600 ok