string转换为pchar怎么确定结束符

在delphi中string类型可以转换为pchar类型,一直都是这么使用的。

如:

var v: string;

var p: pchar;

v := 'hello world';

p := pchar(v);

最近在使用的时候有一个疑问,字符串转换为成pchar时并没有真正的重新分配空间,而是使用了string保存数据的地址,即v[1]的地址,

即pointer(p) == @v[1]

由于pchar是使用#0结尾来判断结束的,那么string类型中一定有一个空闲字节用于保存#0吗? 如果没有的话,如果刚好遇到分配给string的空间后面的一个字节值不为0,pchar就会解析错误。

通过各种情况下堆空间的分配情况来验证实际是怎么样的(在DELPHI2006下测试此处的string 为 ansistring)。

 1 procedure WriteHeap();
 2 var
 3   status: THeapStatus;
 4 begin
 5   status := GetHeapStatus;
 6   Writeln('heap:' + IntToStr(status.TotalAllocated));
 7 end;
 8 
 9 
10 
11 procedure Fun1();
12 var
13   v: string;
14   p: PChar;
15 begin
16   WriteHeap();
17   SetLength(v,12);
18   //设置字符串长度为1 时,堆空间增加大了12,字符串v[1]为实际的内容开始地址
19   //在内容前有8个字节,4个字节用于存储字符串长度,4个字节用于存储引用计数
20   //当设置字符串长度为1时,实际分配了12个字节的空间
21   //当设置长度为3时,分配空间还是12
22   //当设置长度为4时,分配空间为20,增加了8个字节
23   //当设置长度为11时,分配空间还是20
24   //当设置长度为12时,分配空间为28
25   //说明实际分配的数据空间总会空闲一个字节,可能是用来转换pchar时,存储#0使用
26   WriteHeap();
27 end;
28 
29 
30 procedure Fun2();
31 var
32   v: string;
33   p: PChar;
34 begin
35   WriteHeap();
36   SetLength(v,12);
37   WriteHeap();
38 
39   p := pchar(v);
40   //转换pchar后,堆空间并没有增大
41   WriteHeap();
42 
43   //地址是一样的
44   Writeln(Format('%p   %p',[@v[1],Pointer(p)]));
45 end;
46 
47 
48 
49 procedure Fun3();
50 var
51   v: string;
52   p: PChar;
53 begin
54   WriteHeap();
55   v := 'hello world';
56   //堆空间不增大,因为v指向的是字面量值
57   WriteHeap();
58 
59   p := pchar(v);
60   //转换pchar后,堆空间并没有增大 ,p指向的也是字面量值
61   WriteHeap();
62 
63   //地址不一样,因为按索引访问字符串时重新为字符串分配了空间
64   Writeln(Format('%p   %p',[@v[1],Pointer(p)]));
65 
66   //堆空间增大
67   WriteHeap();
68 end;

 

根据运行结果,string转pchar时,实际使用的就是string的数据地址,并且string内部始终会有一个字节用于保存#0,当转换为pchar时使用

如果string指向的值为字面量,在使用索引访问时会重新分配空间

 

posted @ 2020-10-08 17:57  qmcode  阅读(114)  评论(0编辑  收藏  举报