| What are pointers? |
| |
Pointers are a special type of variable. Like a meta-variable. They can point to other variables, or to memory. You might use a record pointer, for example, to point to a block of memory where you have stored lots of record data. You would then use the pointer just as if it were a record variable. We'll see how below.
|
|
| |
When calling Windows APIs (Application Programmer Interfaces), we are obliged to use pointers.
|
|
| |
Types of pointers |
| |
Delphi provides a number of typed pointer types, such as PChar and PExtended, along with a generic, 'point to anything' type - the Pointer type.
|
|
| |
The nice thing about the typed pointers is that they work sensibly with the Inc and Dec functions. Incrementing an PInt64 pointer will add SizeOf(Int64) bytes to the pointer address so that it points to the next Int64 variable in memory.
|
|
| |
The Pointer type is a dangerous one - it falls foul of Delphi's normally tight type handling. Use it with care, or you will end up addressing the wrong memory.
|
|
| |
A simple example using PChar |
| |
The PChar type can be used to scan along a string :
|
|
| |
var
myString : string;
myCharPtr : PChar;
i : Integer;
begin
// Create a string of Char's
myString := 'Hello World';
// Point to the first character in the string
i := 1;
myCharPtr := Addr(myString[i]);
// Display all characters in the string
while i <= Length(myString) do
begin
ShowMessage(myCharPtr^); // Display the string characters one by one
Inc(i);
Inc(myCharPtr);
end;
end; |
|
| |
There are two things to note here. First the use of Addr function to get the address of the string. You could equally use the @ operator. Pointers always work with addresses - the address of a variable here, or a block of acquired memory. Here we point the PChar value to the first character in the string.
|
|
| |
Secondly, now that we have a pointer, we use the ^ character at the end of the pointer name to refer to what the pointer points to. In this case, a character.
|
|
| |
A PChar^ will always give us a character. A PInt64^, for example, will give us an Int64 value. This is where the typing comes in.
|
|
| |
Record pointers |
| |
You can define a pointer to any data type using a different technique:
|
|
| |
var
myRecordPtr : ^TMyRecord; |
|
| |
Here, the ^ symbol is used to dereference the type - we are saying that we do not have a TMyRecord type, but a pointer to one. Note that this is a prefix use of ^.
|
|
| |
Let us create a full record example :
|
|
| |
type
TMyRecord = Record
name : String[20];
age : Integer;
end;
var
myRecord : TMyRecord;
myRecordPtr : ^TMyRecord;
begin
myRecord.name := 'Fred Bloggs';
myRecord.age := 23;
myRecordPtr := @myRecord;
ShowMessage(myRecordptr.name); // Displays 'Fred Bloggs'
end; |
|
| |
When we simpy refer to the record field name, without a ^, Delphi is in fact adding one for us - it recognises what we are doing, and helps us make for more readable code. |