You have been given a lot of good answers at the moment, but starting with the answer that you are already dealing with pointers when using long strings, dynamic arrays and object references, you should start to wonder why you would use pointers instead of long strings, dynamic arrays and object references. Is there a reason to still use pointers, given that Delphi does a good job of hiding them from you in many cases?
Let me give you two examples of using a pointer in Delphi. You will see that this is probably not at all suitable for you if you are mostly writing business applications. However, it can become important if you ever need to use functions of Windows or third-party APIs that are not imported by any of the standard Delphi modules, and for which there are no import units in (for example) JEDI libraries. And that may be the key to achieving the required speed bit in the string processing code.
Pointers can be used to process data types of various sizes (unknown at compile time)
Consider the Windows bitmap data type. Each image can have a different width and height, and there are different formats: from black and white (1 bit per pixel) from 2 ^ 4, 2 ^ 8, 2 ^ 16, 2 ^ 24, or even from 2 ^ 32 gray values or colors , This means that at compile time it is not known how much memory the bitmap will take.
In windows.pas, there is a type of TBitmapInfo:
type PBitmapInfo = ^TBitmapInfo; tagBITMAPINFO = packed record bmiHeader: TBitmapInfoHeader; bmiColors: array[0..0] of TRGBQuad; end; TBitmapInfo = tagBITMAPINFO;
The TRGBQuad element describes one pixel, but the bitmap, of course, contains more than one pixel. Therefore, you should never use a local variable of type TBitmapInfo, but always a pointer to it:
var BmpInfo: PBitmapInfo; begin // some other code determines width and height... ... BmpInfo := AllocMem(SizeOf(TBitmapInfoHeader) + BmpWidth * BmpHeight * SizeOf(TRGBQuad)); ... end;
Now, using a pointer, you can access all the pixels, although TBitmapInfo has only one. Please note that for such code you must disable range checking.
Of course, the same material can be used with the TMemoryStream class, which is basically a friendly wrapper around a pointer to a memory block.
And of course, it’s much easier to just create a TBitmap and assign its width, height, and pixel format. To point it again, Delphi VCL eliminates most cases where pointers would otherwise be needed.
Character pointers can be used to speed up string operations.
This, like most micro optimizations, can only be used in extreme cases, after you have profiled and found the code using strings to consume a lot of time.
A good property of strings is that they are counted by reference. Copying them does not copy the memory that they occupy, it only increases the reference counter. Only when the code tries to change a line that has a reference count greater than 1 will memory be copied to create a line with reference number 1, which can then be safely changed.
The uncommon property of strings is that they are counted by reference. Each operation that can change a string must ensure that the reference count is 1, because otherwise modifying the string would be dangerous. Replacing a character in a string is such a modification. To ensure that the reference count is 1, a call to UniqueString () is added by the compiler whenever a character is written in a string. Now writing n characters of a line in a loop will cause UniqueString () to be called n times, even if after the first time it is ensured that the reference count is 1. This means that basically n - 1 calls to UniqueString () are made unnecessarily.
Using a character pointer is a common way to speed up operations on strings that are associated with loops. Imagine that you want (to display) replace all spaces in a line with a small dot. Use the processor view for the debugger and compare the code executed for this code.
procedure MakeSpacesVisible(const AValue: AnsiString): AnsiString; var i: integer; begin Result := AValue; for i := 1 to Length(Result) do begin if Result[i] = ' ' then Result[i] := $B7; end; end;
with this code
procedure MakeSpacesVisible(const AValue: AnsiString): AnsiString; var P: PAnsiChar; begin Result := AValue; P := PAnsiChar(Result); while P[0] <> #0 do begin if P[0] = ' ' then P[0] := $B7; Inc(P); end; end;
The second function will only have one call to UniqueString () when the address of the first character of the string is assigned to the char pointer.