11.13Binary string constants. 4tH 4tH Forth compiler
Publicité
Publicité
CHAPTER 11. ADVANCED PROGRAMMING
11.12
Multidimensional arrays
147
We’ve seen two dimensional arrays with ’ARRAY’ and ’STRING’, but what about multidimensional arrays. Well, it’s the same thing all over again. C doesn’t actually have multidimensional arrays either. When you define one, just a chunk of memory is allocated.
In 4tH you can do the same thing, but now you have to do it yourself. E.g. when you want to define a matrix of cells of 4 rows by 5 elements, you have to multiply those and allocate an array of that size:
4 5 * array my_array
But what if you want to reference the fourth element of the third row? You cannot write something like:
2 3 my_array @
That’s right. But you can change the behaviour of ”MY_ARRAY” accordingly:
:redo my_array rot 5 * rot + cells
+
;
( n1 n2 -- a)
\ calculate row offset
\ calculate element offset
\ calculate number of cells
\ add to address of my_array
Or even better:
4 5 * array my_array does> rot 5 * rot + cells + ;
This word calculates the correct offset for you. Note that the third row is row number two
(since we start counting from 0) and the fourth element is element number three:
2 3 my_array @
You can also use "MY_ARRAY" to initialize an array, since it simply calculates the correct address for you:
5 2 3 my_array !
\ sets 3rd row 4th element to 5
You can add more dimensions if you want. This works basically the same way: create an array of a size that equals the products of its dimensions and design a word that calculates the correct address.
11.13
Binary string constants
A binary string constant is an unterminated string that doesn’t necessarily contain characters. Creating binary string constants is easy. Just compile them by their ASCII value into the String Segment with ’C,’: char H c, char i c, char ! c, 0 c,
CHAPTER 11. ADVANCED PROGRAMMING 148
The fun of it all is that 4tH doesn’t allow you to access the String Segment directly, so you can never retrieve them. You need ’OFFSET’ to define a word which does all the hard work for you. At runtime it takes an index and leaves the ASCII value of the character in question on the stack. ’OFFSET’ is used just before you compile the ASCII values: offset greet char H c, char i c, char ! c, 0 c,
Note that you have to terminate a binary string constant manually if you need to, although it is perfectly legal to create binary string constants with no termination at all. Retrieving characters is easy. This will print ”Hi!”:
0 greet emit
1 greet emit
2 greet emit cr
And so will this:
0 begin dup greet dup while emit 1+ repeat drop drop
\ setup index
\ retrieve character
\ if not terminated
\ emit and increase index
\ clear stack
You can use binary string constants for compact tables, bitstrings or any other raw data as long as each element doesn’t exceed the size of a single character. Although useful in itself, you’ll get into trouble when you try to pack several binary strings in a single datastructure.
Sure, you can give each binary string its own ’OFFSET’ but binding their addresses into some form of array structure? No, because an ’OFFSET’ is not a literal expression and hence cannot be compiled that way.
A solution is to ”tag” individual strings. Tags are literal expressions and compilable, so you can do this:
OFFSET names
TAG names Hans char H c, char a c, char n c, char s c, 0 c,
TAG names Wil char W c, char i c, char l c, char 0 c,
TAG names Phil char P c, char h c, char i c, char l c, 0 c,
You can feed the ’TAG’ as an index to an ’OFFSET’, so this will return ”W” (from ”Wil”):
Wil names emit
And as promised, this will work as well:
CREATE developers
Hans , Phil , Wil , NULL ,
Contrary to popular belief, this construct is as memory efficient as:
CREATE developers
," Hans" ," Phil" ," Wil" NULL ,
Télécharger
Publicité