Delphi中的PChar、String、Char数组

参考:http://blog.csdn.net/procedure1984/article/details/5419616

 

一、三者的区别

  string和char数组都是一块内存,其中存放着连续的字符。

  string保存具体字符的内存对用户是透明的,有Delphi管理它的分配、复制和释放,用户不能干预(其实也可以,不过是通过非法途径)

  Char数组类似于C/C++中的字符数组

  PChar是一个指针,它的大小只有32位。定义时由Delphi自动填0.要将PChar作为字符串使用的话,必须自己分配内存并在使用完之后进行释放。PChar型字符串由#0表示字符串的结尾。Delphi所提供的相关的PChar字符串的操作都是判断#0来决定字符串的结尾的

  因为PChar是指针,所以它能指向任何地方(也就是说,它不一定非要指向字符串不可)。

  把一个String赋值给PChar,只是将String中保存具体字符串的内存的地址赋值给PChar变量。当然也可以把Char数组第一个元素的地址赋值给PChar

  一般的占用内存大小关系:Char数组<PChar(指分配过字符串的)<String(除了具有字符串外还包括字符串的一些其他信息)

  如果是空字符串,那么:Pchar<String<array[0..n] of Char

  从速度上来说,无疑string是最慢的,例如:作为参数传递(非var调用时)给过程时string将整个字串赋值,并将副本传递过去,PChar将指针本身的副本传递过去(32位),Char数组和PChar一样,传递的是第一个元素的地址副本

  不过从灵活性上来说,string最高,而且Delphi支持的函数最多。另外可以将string作为Buffer使用(因为它当中可以包含字符0),这是一个很重要的技巧

1.在Delphi2.0以后的版本中, string分两种, 

  一种是与Pascal传统string相兼容,叫ShortString, 
  它的存储结构如下: 
     +---------------------+    
     | 1Byte |    字符串内容 | 
     +---------------------+ 
     0         1 ...... 
  其中第一个字节为字符串的长度。 
  所以ShortString所能包括的字符串长度不能大于255。 
  另一种是叫长字符串AnsiString,    它就是一个指向字符串的指针,不过具体的存储有些特别。 
  它的存储结构如下: 
    +-----------------------+ 
    | 4B | 4B |    字符串内容 | 
    +-----------------------+ 
    -8     -4     0    ...... 
  其中,AnsiString指向字符串第一个字符, 
  在第一个字符的反方向第1到第4的4个字节表示字符串长度,第5到第8的4个字节表字符串被引用的次数。

  AnsiString 是Delphi 独有的,其存储区在运行时动态分配的并有自动回收功能,因为这个功能AnsiString有时被称为生存期自管理类型

  当两个或更多的AnsiString类型共享一个指向相同物理地址的引用时,Delphi 使用了Copy–On-Write 的技术,即一个字符串要等到修改结束,才释放一个引用并分配一个物理字符串。下面的例子有助于理解这些概念:

var
  S1, S2: string;
begin
  S1:=‘Example for Copy-On-Write...‘; // 给S 1 赋值,S 1 的引用计数为1

  S2:=S1;                            // 现在S 2 与S 1 指向同一个字符串, S 1 的引用计数为2

  S2:=S2+‘Changed ‘ ;               // S 2 现在改变了,所以它被复制到自己的物理空间,并且S 1 的引用计数减1。
end;

 

2.pchar就是纯指向字符串(#0字符结尾)的指针,与C语言中的char *是一样的。

3.char数组也是指向字符串的指针,它与pchar的区别在于: 
      1.char数组(均指非动态数组)一旦定义好,它的长度就固定了; 

      2.char数组的地址是常量,不能另赋其它值,不能象pchar一样, 
         如: sPchar:pchar; sArray1,sArray2:array[0..80]of char; 
           sPChar:=sArray2; sPChar;=sArray1; 
           但不能sArray2:=sArray1; 

 

4.三者的区别的简介

  要说速度最快当然是纯指针操作的pchar与char数组最快啦所谓占内存最少,效率更高, 

  不知老兄你想进行什么方面的应用,一般对string,pchar或char数组,不用考虑这些。

  对编程而言,如果在Delphi或C++Builder中使用,可尽量使用AnsiString,Borland公司对它已经进行了非常完美的内部处理, 使用非常方便。 

  如果涉及到Windows API或混合编程等,接口部分一般使用pchar。

  char数组使用的比较少了,因为多数可以用char数组的地方,都可以使用PChar分配内存来代替

  现在比较流行的作法是定义一个ansistring, 再用setlength来设定它的长度

 

5.字符串string 字符数组与指向字符串的指针pchar的区别与联系 

  这3者的基本概念相同,但有一些非常细微的差别,在编程时稍不注意就会出错,需高度重视。 

  使用指向字符串的指针,如果不是以0结尾,运行时就会出现错误。为了避免这种错误,需要在字符串结尾人工加入0 即char(0),或用strpcopy函数在字符串结尾自动加0。 

  例1: 指向字符串的指针,如果不是以0结尾,运行时会出现错误: 

{s[0]=3 s[1]=‘n‘ s[2]=‘e‘ s[3]=‘w‘}
var
    s: String;
    p: PChar;
begin
    s:= ‘new‘;
    label1.caption:= s;    {‘new‘}
    label2.caption:= intToStr(Integer(s[0]));    {3是字符串的长度}
    //通过访问string变量的s[0]来获取该string的长度,对应的字符串存储在s[1]以及s[1]之后,并且string字符串并不是以0结尾的

    p:= @s[1];    {不是以0结尾的,莫用PChar型指针}
    label3.caption:=strpas(p);    {运行时出现错误}
end;

  例2:在字符串结尾人工加上0即char(0),可是用指向字符串的指针

{s[0]=4 s[1]=‘n‘ s[2]=‘e‘ s[3]=‘w‘ s[4]=0}
var
    s: String;
    p: PChar;
begin
    p:=@s[1];    //p指向s[1]的地址,是因为string类型字符串是存储在s[1]及其之后的,而s[0]部分存储的是字符串的长度
    
    s:= ‘new‘+char(0);    {以0结尾,可以用PChar型指针
    label1.caption:= strpas(p);
end;

  

 

二、三者之间的相互转换

  设有以下三个变量

var
    s: string;
    p: PChar;
    a: array[1..20] of char;

  那么三者之间的转换如下

1.字符串到PChar  

p:= PChar(s);
//但是要注意PChar和string的区别
//严格来说应该是
//p:= PChar(s+char(0));当然上面的方法也是可以的,因为会在编译的时候进行过处理和优化

2.Pchar到字符串

s:= p;

3.PChar到字符数组

StrCopy(@a, p);

4.字符数组到PChar

PChar(@a);

5.字符串与字符数组之间的转换

  字符串与字符数组之间的转换就只有通过PChar来中转了。例

procedure TForm1.btnClick(Sender: TObject);
var
    str: array[0..10] of char;
begin
    StrCopy(@str, PChar(mmo1.Text));
    mmo2.Text:= PChar(@str);
end;

  

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。