2009-02-14 62 views
4

我有方法(DELPHI 2009):将AnsiString强制转换为PAnsiString时会发生什么?

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

这是基类,其中一个抽象方法“值:指向”预计相应的数据的指针,如:

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

所以我尝试通过这样的价值:

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

但从ANSIString长到PAnsiString不工作演员,我明白为什么,但我想知道什么样的结果铸造是。所以我写了一个简单的测试:

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; 

结果是:

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

其中:

- 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? 

什么是P1和P4的含义是什么?

回答

7

尼斯难题,但是我有解决方案:

  • P2和P3是指向缓冲区的指针
  • P1和P4的地址的缓冲区的地址
  • P5是在缓冲器中的第一元件

我已经添加在代码注释:

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; 
15

AnsiString被实现为一个指针。一个AnsiString变量只包含一个地址。地址是字符串中第一个字符的地址,如果字符串为空,则地址为nil

A PAnsiString是指向AnsiString变量的指针。它是一个指向字符串第一个字符的指针。当你说PAnsiString(Buffer)时,你告诉编译器将Buffer中的指针看作是指向AnsiString的指针,而不是指向字符数据的指针。地址5006500是该字符串的第一个字符的位置,即C

您在存储器内的记录,它表示字符串:

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

Buffer保持在它的C字节的地址。您可以将其输入为具有类型PAnsiString而不是AnsiString。你告诉编译器你有这样的布局:

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

当我对指针进行推理时,我画这样的图。如果你的桌子上没有放置一些纸张,那么你会对自己造成伤害。

+0

@Rob:我不能在旁边没有纸张的情况下工作。感谢您的解释。 – 2009-02-14 20:16:40

相关问题