将静态分配的字符串复制到动态分配的字符串中



我举了一个例子,试图向自己解释它的作用:

: 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

我认为Will Hartung答案的第一部分是正确的。

正如他所描述的,正在使用的字符串表示,即字符计数,然后是实际字符串。

因此,在您的示例中,c!将字符串的长度存储在以ptr2开头的内存的第一个单元中。

因此,如果你想检索字符串,你只需要知道地址,然后你可以从该地址中提取长度n,并从地址+1开始提取n个字符。

在Forth中,至少在这种特定情况下,字符串的长度在内存中字符串的START处指定。例如,在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 ;

因此:

s" Hello! " name copy-string

然后,你可以做:

: 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

相关内容

  • 没有找到相关文章