String 将静态分配的字符串复制到动态分配的字符串中
我在跟踪一个,试图向自己解释它的作用:String 将静态分配的字符串复制到动态分配的字符串中,string,memory-management,forth,String,Memory Management,Forth,我在跟踪一个,试图向自己解释它的作用: : place \ ptr len ptr2 2dup \ ptr len ptr2 len ptr2 >r >r \ ptr len ptr2 char+ \
: place \ ptr len ptr2
2dup \ ptr len ptr2 len ptr2
>r >r \ ptr len ptr2
char+ \ ptr len (ptr2 + 1)
swap \ ptr (ptr2 + 1) len
chars \ ptr (ptr2 + 1) (len * char)
cmove \ --
\ from to how-many
r> r> \ ptr2 len
c! ; \ len = ptr2 ???
\ s" Hello! " name place
这一切都是有道理的,直到最后一个指令。。。我哪里出错了
编辑:
我添加了一些跟踪:
: place \ ptr len ptr2 |
2dup cr .s \ ptr len ptr2 len ptr2 | <5> 16490736 5 2126333248 5 2126333248
>r >r cr .s \ ptr len ptr2 | <3> 16490736 5 2126333248
char+ cr .s \ ptr len (ptr2 + 1) | <3> 16490736 5 2126333249
swap cr .s \ ptr (ptr2 + 1) len | <3> 16490736 2126333249 5
chars cr .s \ ptr (ptr2 + 1) (len * char) | <3> 16490736 2126333249 5
cmove cr .s \ -- | <0>
\ from to how-many |
r> r> cr .s \ ptr2 len | <2> 5 2126333248 ok
c! ; \ ptr2 = len ??? |
\ s" Hello! " name place
:放置\ptr len ptr2|
2dup cr.s\ptr len ptr2 len ptr2 | 16490736 5 2126333248 5 2126333248
>r>r.s\ptr len ptr2 | 16490736 5 2126333248
char+cr.s\ptr len(ptr2+1)124907365 2126333249
交换cr.s\ptr(ptr2+1)len | 16490736 2126333249 5
chars cr.s\ptr(ptr2+1)(len*char)124907362126333249 5
cmove cr.s \--
\从到多少|
r> r>cr.s\ptr2透镜| 5 2126333248正常
c!ptr2=len|
\“你好!”说出地点
在Forth中,至少在这种特定情况下,字符串的长度在内存中字符串的开头指定。例如,在C语言中,字符串是以0结尾的字节段。在Forth和其他语言(如Pascal)中,字符串与它们有一个关联的长度,并且通常,如本例所示,长度位于字符串的开头
因此,对于字符串“HELLO”,字节如下所示
05 H E L L O
字符串的开头指向包含5的字节
您的代码定位字符串,跳过长度(首先是char+
),然后为执行此操作的cmove
初始化字符串
最后,它将长度复制到新字符串的开头
例如,使用place
是错误的,因为您没有指定副本的长度。这需要将长度作为堆栈上的第二个参数
因此,你的例子应该是:
s" Hello! " 7 name place \ 7 because of the space after the Hello!, the quote is the
\ delimiter, not the space. The leading spaces are ignored
奇怪的是,理论上不需要将长度传递给单词,它已经存在于字符串中了。如果要复制子集,可以指定长度
你也可以这样看。给定place
原样,您可以写一个简单的单词:
: copy-string ( string-src dest -- )
>r \ string-src
dup \ string-src string-src
c@ \ string-src length
<r \ string-src length dest
place ;
然后,你可以做:
: type-string ( string-src )
dup \ string-src string-src
c@ \ string-src length
type ; \ type out the string, type requires addr and length
因此:
我认为威尔·哈东回答的第一部分是正确的 正在使用的字符串表示如他所述,即字符计数,然后是实际字符串 所以在你的例子中
c
将字符串的长度存储在以ptr2
开头的内存的第一个单元中
因此,如果您想检索字符串,只需要知道地址,就可以从该地址获取长度n,获取n个字符,从地址+1开始。您可能想再次查看该示例。这不是“我使用的例子”,我复制了链接页面中的例子。我还测试了它,它就像广告上说的那样工作。。。另外,这可能会让您感到困惑,在我在代码附近写的注释中,堆栈的顶部在右边(最右边的元素将首先从堆栈中取出)。实际上,按照您编写的方式,我得到了一个“无效内存地址”错误。很抱歉,我花了很长时间才回复。是的,现在我明白我的错误在哪里了。我以为在堆栈之间移动数据是fifo,但它是lifo,所以我现在明白发生了什么。不用担心!我很高兴你把它解决了。
: type-string ( string-src )
dup \ string-src string-src
c@ \ string-src length
type ; \ type out the string, type requires addr and length
create name 10 allot
s" Hello! " name copy-string
name type-string