I have the method (Delphi 2009):
procedure TAnsiStringType.SetData(const Value: TBuffer; IsNull: boolean = False);
begin
if not IsNull then
FValue:= PAnsiS
Nice puzzle, but I have the solution:
I have added comment in the code:
var
Buffer: AnsiString;
P1: Pointer;
P2: Pointer;
P3: Pointer;
P4: Pointer;
P5: Pointer;
begin
P1:= PAnsiString(Buffer);
(* A cast from AnsiString to PAnsiString has no real meaning
because both are a pointer to a block of characters ()
P2:= Addr(Buffer);
P3:= @Buffer;
(* Both Addr and @ give the address of a variable. The variable Buffer is
a pointer so we get the address of the pointer, not the value of the
pointer. *)
P4:= Pointer(Buffer);
(* See the remark on P1. Due to the cast both give the same result. *)
P5:= PChar(Buffer[1]);
(* This looks like a pointer to the first element. But the cast changes
it into the character. *)
WriteLn('P1: ' + IntToStr(Integer(P1)));
WriteLn('P2: ' + IntToStr(Integer(P2)));
WriteLn('P3: ' + IntToStr(Integer(P3)));
WriteLn('P4: ' + IntToStr(Integer(P4)));
WriteLn('P5: ' + IntToStr(Integer(P5)));
end;
An AnsiString
is implemented as a pointer. An AnsiString
variable holds nothing but an address. The address is that of the first character in the string, or nil
if the string is empty.
A PAnsiString
is a pointer to an AnsiString
variable. It's a pointer to a pointer to the first character of a string. When you say PAnsiString(Buffer)
, you're telling the compiler to treat the pointer in Buffer
as though it were a pointer to an AnsiString
instead of a pointer to character data. The address 5006500 is the location of the first character of the string, C
.
You have a record in memory that represents the string:
+-----------+ | $ffffffff | -1 reference count (4 bytes) +-----------+ Buffer: | $00000001 | length (4 bytes) +---------+ +-----------+ | 5006500 | --> | 'C' | first character (1 byte) +---------+ +-----------+ | #0 | null terminator (1 byte) +-----------+
Buffer
holds the address of the byte with C
in it. You type-cast that to have type PAnsiString
instead of AnsiString
. You told the compiler that you had this layout:
+-----------+ | ... | +-----------+ Buffer: | ... | +---------+ +-----------+ +-----------+ | 5006500 | --> | $00000043 | --> | garbage | first character +---------+ +-----------+ +-----------+ | ... | +-----------+
When I'm reasoning about pointers, I draw diagrams just like this. If you don't keep some paper next to you on your desk, you're doing yourself a disservice.