Pointers and memory access
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 fieldThere 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.
- 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 variablesStructure 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 arrayStructure 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\xPointers 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.
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 variableTo 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.
ExampleStructure 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 procedureThe 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 '()'.
ExampleProcedure 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())