我有方法(Delphi 2009):
procedure TAnsiStringType.SetData(const Value: TBuffer; IsNull: boolean = False);
begin
if not IsNull then
FValue:= PAnsiString(Value)^;
inherited;
end;
这是基类上的抽象方法,其中“Value:Pointer”需要相应数据的指针,如:
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是什么意思?
答案 0 :(得分:15)
AnsiString
被实现为指针。 AnsiString
变量只保存一个地址。地址是字符串中第一个字符的地址,如果字符串为空,则为nil
。
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 +---------+ +-----------+ +-----------+ | ... | +-----------+
当我推理指针时,我就像这样绘制图表。如果你不在桌子旁边放一些纸,那么你自己也会受到伤害。
答案 1 :(得分:7)
很好的谜题,但我有解决方案:
我在代码中添加了评论:
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;