1

I was following an example, trying to explain to myself what it does:

: 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

It all made sense, until the last instruction... where did I go wrong?

EDIT:

I've added some tracing:

: 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
4

2 回答 2

1

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

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

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

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

于 2013-08-09T10:09:00.843 回答
1

在 Forth 中,至少在这种特定情况下,字符串的长度在内存中字符串的 START 处指定。例如,在 C 中,字符串是由 0 终止的字节的延伸。在 Forth 和其他语言(如 Pascal)中,字符串具有与它们相关的长度,并且通常,在这种情况下,长度位于开头字符串。

因此,对于字符串“HELLO”,字节看起来像

05 H E L L O

字符串的开头指向其中包含 5 的字节。

您的代码定位字符串,跳过长度(即 first 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
于 2013-08-08T22:37:54.520 回答