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