What happens when AnsiString is passed to PAnsiString?

I have a method (Delphi 2009):

procedure TAnsiStringType.SetData(const Value: TBuffer; IsNull: boolean = False); begin if not IsNull then FValue:= PAnsiString(Value)^; inherited; end; 

This is an abstract method in the base class, where "Value: Pointer" expects a pointer to the corresponding data, for example:

 String = PString AnsiString = PAnsiString Integer = PInteger Boolean = PBoolean 

So, I am trying to pass the value as follows:

 var S: AnsiString; begin S:= 'New AnsiString Buffer'; SetBuffer(PAnsiString(S)); end; 

But casting from AnsiString to PAnsiString does NOT work, I can understand why, but I want to know what the result of casting is. So I wrote a simple test:

 var Buffer: AnsiString; P1: Pointer; P2: Pointer; P3: Pointer; P4: Pointer; begin P1:= PAnsiString(Buffer); P2:= Addr(Buffer); P3:= @Buffer; P4:= Pointer(Buffer); P5:= PChar(Buffer[1]); 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; 

Result:

 P1: 5006500 P2: 1242488 P3: 1242488 P4: 5006500 P5: 67 

Where:

 - P2 and P3, is the address of Buffer: AnsiString - P5 is the Char Ord value of Buffer[1] char, in this case "67 = C" - How about P1 and P4? 

What is the meaning of P1 and P4?

+4
source share
2 answers

Good puzzle, but I have a solution:

  • P2 and P3 - buffer pointer address
  • P1 and P4 - buffer address
  • P5 - the first item in the buffer

I added a comment to 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; 
+7
source

An AnsiString is implemented as a pointer. The AnsiString variable contains nothing but an address. The address is the address of the first character in the string, or nil if the string is empty.

A PAnsiString is a pointer to an AnsiString variable. This is a pointer to a pointer to the first character of a string. When you say PAnsiString(Buffer) , you tell the compiler to process the pointer in Buffer , as if it were a pointer to 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 memory entry that represents a string:

  + ----------- +
                 |  $ ffffffff |  -1 reference count (4 bytes)
                 + ----------- +
 Buffer: |  $ 00000001 |  length (4 bytes)
 + --------- + + ----------- +
 |  5006500 |  -> |  'C' |  first character (1 byte)
 + --------- + + ----------- +
                 |  # 0 |  null terminator (1 byte)
                 + ----------- +

Buffer contains the address of the byte with C in it. You enter a type to be of type PAnsiString instead of AnsiString . You told the compiler that you have this layout:

  + ----------- +
                                   |  ... |
                                   + ----------- +
 Buffer: |  ... |
 + --------- + + ----------- + + ----------- +
 |  5006500 |  -> |  $ 00000043 |  -> |  garbage |  first character
 + --------- + + ----------- + + ----------- +
                                   |  ... |
                                   + ----------- +

When I talk about pointers, I draw diagrams that way. If you do not keep some paper next to you on your desk, you are doing yourself a disservice.

+15
source

All Articles