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指向的值为字面量,在使用索引访问时会重新分配空间