Pointers and memory access

Pointers

Using pointers is possible by placing one '*' (asterix) in front of the name of a variable, array, list or map. A pointer is a placeholder for a memory address which is usually associated to a structure.

Example

  *MyScreen.Screen = OpenScreen(0, 320, 200, 8, 0)
  mouseX = *MyScreen\MouseX  ; Assuming the Screen structure contains a MouseX field
There are only three valid methods to set the value of a pointer:
- Get the result from a function (as shown in the above example)
- Copy the value from another pointer
- Find the address of a variable, procedure or label (as shown below)

Note: unlike C/C++, in SpiderBasic the '*' is always part of the item name. Therefore '*ptr' and 'ptr' are two different variables. 'ptr' is a variable (regular one) storing a value, '*ptr' is another variable of pointer type storing an address.

Pointers and memory size

Because pointers receive only addresses as values, the memory size of a pointer is the space allowing to store an absolute address of the processor:
- On 32-bit processors the address space is limited to 32-bit, so a pointer takes 32-bit (4 bytes, like a 'long') in memory
- On 64-bit processors it takes 64-bit (8 bytes, like a 'quad') in memory, because the absolute address is on a 64-bit range.

As a consequence the type of a pointer depends of the CPU address mode, (‘long' on 32-bit CPU and ‘quad' on 64-bit one for example), so a pointer is a variable of type pointer.
It results from this that assigning a native type to a pointer (*Pointer.l, *Pointer.b ...) makes no sense.

Note:
- Every time a memory address needs to be stored in a variable, it should be done through a pointer. This guaranteed address integrity at the compilation time whatever the CPU address mode is.

Pointers and structures

By assigning a structure to a pointer (for example *MyPointer.Point) it allows to access any memory address in a structured way (with the operator ‘\').

Example: Pointers and variables

  Structure Point
    x.l
    y.l
  EndStructure
  
  Define Point1.Point, Point2.Point
  
  *CurrentPoint.Point = @Point1  ; Pointer declaration, associated to a structure and initialized with Point1's address
  *CurrentPoint \x = 10          ; Assign value 10 to Point1\x
  
  *CurrentPoint.Point = @Point2  ; move to Point2's address
  *CurrentPoint \x = 20          ; Assign value 20 to Point2\x
  
  Debug Point1\x
  Debug Point2\x

Example: Pointers and array

  Structure Point
    x.l
    y.l
  EndStructure
  
  Define Point1.Point, Point2.Point
  
  Dim *Points.Point(1) ; 2 slots array
  *Points(0) = @Point1 ; Assign the first point variable to the first array slot
  *Points(1) = @Point2 ; Same for second

  *Points(0)\x = 10 ; Modify the variables trough the pointers
  *Points(1)\x = 20 ;
  
  Debug Point1\x
  Debug Point2\x
Pointers allow to move, to read and to write easily in memory. Furthermore they allow programmers to reach big quantities of data without supplementary cost further to data duplication. Copying a pointer is much faster.

Pointers are also available in structures, for more information see the structures chapter.

Pointers Arithmetic

In SpiderBasic, a pointer can't be moved by adding or substracting a number. A pointer is only allowed on a structured element. A memory buffer allocated with AllocateMemory() is not allowed. AllocateStructure() needs to be used if a pointer is a required on a dynamically allocated element.

Address of variable

To find the address of a variable in your code, you use the 'at' symbol (@). A common reason for using this is when you want to pass a structured type variable to a procedure. You must pass a pointer to this variable as you cannot pass structured variables directly.

Example

  Structure People
    Age.b
    Name$
  EndStructure
  
  Procedure SetInfo(*People.People)
    *People\Age = 69
    *People\Name$ = "John"
  EndProcedure
  
  Define.People King
  
  SetInfo(@King)
  
  Debug King\Age
  Debug King\Name$

Address of procedure

The most common reason to get the address of a procedure is when dealing with callbacks. Many commands in SpiderBasic requires callbacks as parameter, like BindEvent(), BindGadgetEvent(), ReadFile() etc. The address of a procedure is got using the 'at' symbol (@) in front of the procedure name including the '()'.

Example

  Procedure ButtonHandler()
    Debug "Button click event on gadget #" + EventGadget()
  EndProcedure
  
  OpenWindow(0, 100, 100, 200, 50, "Click test", #PB_Window_SystemMenu)
    ButtonGadget(0, 10, 10, 180, 30, "Click me")
  
  BindGadgetEvent(0, @ButtonHandler())