08Pointers and the heap
Pointer arithmetic
Step a pointer through a block of values, measure distances, and compare addresses.
A block from the heap holds its values next to each other, like a row of boxes. Adding a
number to a pointer moves it along the row: ကိန်းများ + ၁ is the next box, ကိန်းများ + ၂ the one
after. The boxes are numbered from 0, so the first box is ကိန်းများ + ၀, which is just
ကိန်းများ.
Expected output
၁၀
၂၀
၃၀
+ ၁ moves one integer along, not one octet. The pointer's kind tells how big a box
is, and Zaka steps over that number of octets on its own.
Which value does ၏ တန်ဖိုး read?
၏ တန်ဖိုး reads the value at the whole expression written before it, so ကိန်းများ + ၁ ၏ တန်ဖိုး
is "the value at (list + 1)". The short form * binds to the name right after it, so
*ကိန်းများ + ၁ is "(the value at list) + 1":
Expected output
၂၀
၁၁
The same rule bites when a pointer comes second. စုစုပေါင်း + ညွှန်း ၏ တန်ဖိုး is "the value at
(total + pointer)", not "total + the value at the pointer". Put the read in parentheses,
စုစုပေါင်း + (ညွှန်း ၏ တန်ဖိုး), or use the short form, စုစုပေါင်း + *ညွှန်း.
Walking with a pointer
Pointers into the same block can be compared, so a loop can walk a pointer from the
first box to the end. The end is ကိန်းများ + ၃, the place just past the last box: the
loop compares against it but never reads it.
Expected output
၀
၁
၄
၃
Subtracting two pointers gives the number of boxes between them, as a ကိန်းပြည့်.
ကိန်းများ ၏ တန်ဖိုးအငှား lends the block: ညွှန်း borrows it and ကိန်းများ keeps it.
An address made with + or - is a borrow as well, so it never needs the word. Ownership
and borrowing has the rules.
| Form | Gives |
|---|---|
ပ ၏ တန်ဖိုးအငှား | a borrow of the block ပ owns; ပ keeps it |
ပ + ၂, ပ နှင့် ၂ ၏ ပေါင်းလဒ် | a pointer two boxes on |
ပ - ၂, ပ နှင့် ၂ ၏ နုတ်လဒ် | a pointer two boxes back |
ပ - မ | the number of boxes from မ to ပ |
ပ သည် မ အောက် ငယ် | whether ပ comes before မ |
ပ သည် ဗလာ နှင့် ညီ | whether ပ is null |
Nothing else works on pointers. A pointer times a number, for example, makes no sense:
Expected error
error[ZK0415]: the operator "*" cannot be used on pointers
Reading the same octets as another kind
A conversion turns a pointer of one kind into another. This program asks for 8 octets, stores a 1-octet code in the first one, and a 32-bit price in octets 4 to 7:
Expected output
၁၅၀၀
Building a record from hand-counted octets like this invites mistakes. A later version of Zaka adds records, which do the counting on their own.
An opaque လိပ်စာ converts to and from each pointer kind on its own, as long as the boxes
of that kind hold no address. It has no box size, so a program cannot add to it or read
through it until it is converted. A pointer to a pointer, such as
ကိန်းပြည့် လိပ်စာ ၏ လိပ်စာ, does not pass through လိပ်စာ, on its own or with one
conversion: that would read stored addresses as other data, which the checker cannot
follow. It goes through a raw address, <kind> လိပ်စာအကြမ်း, in two conversions.
Hands on
- Fill a block of 10 integers with the numbers 1 to 10, then print their sum.
- Walk a pointer backwards, from the last box to the first.
- Read one box past the end of the block. Pointer mistakes explains what happens.
Next: Growing and shrinking.