2013-08-08 4 views
1

je suivais un example, en essayant de me expliquer ce qu'il fait:chaîne allouée statiquement dans allouée dynamiquement un

: 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 

Tout fait sens, jusqu'à ce que la dernière instruction ... où est-ce que je me trompe ?

EDIT:

J'ai ajouté quelques traçage:

: 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 

Répondre

1

Je pense que la première partie de la réponse de Will Hartung est correct.

La représentation de chaîne utilisée est telle que décrite, à savoir un nombre de caractères, puis la chaîne réelle. Dans votre exemple, c! enregistre la longueur de la chaîne dans la première cellule de la mémoire qui commence par ptr2.

Donc, si vous voulez récupérer votre chaîne que vous n'aurez besoin de connaître l'adresse, vous pouvez alors chercher à cette adresse pour obtenir la longueur n, et la récupération n caractères à partir de l'adresse + 1.

+1

Désolé, il m'a fallu une éternité pour répondre. Oui, maintenant j'ai compris où était mon erreur. Je pensais que déplacer des données entre les piles était fifo, mais c'est lifo, donc je comprends ce qui est arrivé, maintenant. –

+0

Ne vous inquiétez pas! Je suis content que tu l'as réglé. – sheepez

1

à Forth, au moins dans ce cas précis, des chaînes ont leur longueur spécifiée au début de la chaîne en mémoire. En C, par exemple, les chaînes sont des tronçons d'octets terminés par un 0. Dans Forth, et dans d'autres langages tels que Pascal, les chaînes ont une longueur associée avec eux, et typiquement, comme dans ce cas, la longueur est au début de la chaîne.

Ainsi, la chaîne « BONJOUR », les octets ressemblerait

05 H E L L O 

Et le début des points de chaîne à l'octet avec le 5 en elle.

Votre code localise la chaîne, passe la longueur (char+ d'abord), puis l'amorce pour le cmove, qui fait le travail. A la fin, il copie la longueur au début de la nouvelle chaîne.

Vous utilisez l'exemple de place est faux, car vous ne spécifiez pas la longueur de la copie. Cela nécessite la longueur en tant que second argument sur la pile.

Ainsi, votre exemple devrait être:

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 

La partie étrange à ce sujet est que, en théorie, il n'y a pas besoin de passer la longueur du mot, il est déjà là dans la chaîne. Vous devez spécifier la longueur si vous souhaitez copier un sous-ensemble.

Vous pourriez aussi le voir de cette façon. Étant donné place tel qu'il est, vous pouvez écrire un mot simple:

: copy-string (string-src dest --) 
    >r       \ string-src 
    dup       \ string-src string-src 
    [email protected]       \ string-src length 
    <r       \ string-src length dest 
    place ; 

Alors:

s" Hello! " name copy-string 

Ensuite, vous pouvez faire:

: type-string (string-src) 
    dup   \ string-src string-src 
    [email protected]   \ string-src length 
    type ;  \ type out the string, type requires addr and length 

Alors:

create name 10 allot 
s" Hello! " name copy-string 
name type-string 
+0

Vous probablement vouloir revenir sur l'exemple à nouveau. Ce n'est pas "mon utilisation de l'exemple", je l'ai copié tel quel de celui de la page liée. Je l'ai aussi testé, et ça a marché comme annoncé ... Aussi, peut-être que ça vous a rendu confus, dans les commentaires que j'ai écrits près du code, le haut de la pile est à droite (l'élément le plus à droite serait pris en premier empiler). –

+0

En fait, comme vous l'avez écrit, je reçois une erreur "adresse mémoire invalide". –

Questions connexes