Pointers
A pointer holds the address of a value. Through it you can read and write the value from somewhere that does not know its name, which is how heap memory is reached and how linked structures are built.
'' An address, and what lives at it.
dim as int32 n = 10
dim as int32 ptr p = @n '' @ takes the address
print "*p ="; *p '' * reads what p points at
*p = 20 '' ...or writes it
print "n is now"; n
type Point
as int32 x, y
end type
dim as Point pt = ( 3, 4 )
dim as Point ptr pp = @pt
pp->x = 30 '' -> reaches a field
print "pt is"; pt.x; pt.y
'' Arithmetic counts elements, not bytes.
dim as int32 a( 0 to 4 ) = { 10, 20, 30, 40, 50 }
dim as int32 ptr first = @a( 0 )
print "first[2] ="; first[2]; ", *( first + 3 ) ="; *( first + 3 )
dim as uint8 ptr bytes = cast( uint8 ptr, first )
print "int32 ptr + 1 moves"; cast( integer, first + 1 ) - cast( integer, first )
print "uint8 ptr + 1 moves"; cast( integer, bytes + 1 ) - cast( integer, bytes )
'' Walking a run of elements, and the distance between two pointers.
dim as int32 ptr lastOne = @a( 4 ), q = first
print "walked:";
do while q <= lastOne
print *q;
q += 1
loop
print
print "lastOne - first ="; lastOne - first
Output
*p = 10
n is now 20
pt is 30 4
first[2] = 30, *( first + 3 ) = 40
int32 ptr + 1 moves 4
uint8 ptr + 1 moves 1
walked: 10 20 30 40 50
lastOne - first = 4
| Written | Means |
|---|---|
int32 ptr | the type: an address of an int32 |
@n | the address of n |
*p | the value at p, for reading or writing |
p->x | field x of the record at p; the same as ( *p ).x |
p[i] | the element i places after p; the same as *( p + i ) |
Writing through *p changed n, because p holds n's address: there is
one value and two ways to reach it.
Pointer arithmetic counts elements, not bytes. first + 1 is the next
int32, four bytes on; the same step on a uint8 ptr is one byte. That is
why a pointer to an array's first element can be indexed like the array, and
why subtracting two pointers into one array gives the number of elements
between them, 4 here.
@v + 3, with v an int32, is not three bytes past v: it is three
int32s, twelve bytes, outside v altogether. Reading there returns
whatever is next in memory and nothing reports it. To step in bytes, step
through a byte pointer: cast( uint8 ptr, @v ) + 3.
cast( uint8 ptr, first ) reinterprets an address as a pointer to another
type. any ptr is an address with no type at all: every pointer converts to
it and back without a cast, and it cannot be dereferenced until you convert it
to a typed pointer.
Activities
- Print the bytes of the
int32value 258 through auint8 ptr. Which byte comes first? - Walk
abackwards with a pointer, fromlastOnedown tofirst.