因为要调用 windows 的 api 或者给 vc++ 写接口,很多地方都要用到 pchar,现在将 char 数组、string 和 pchar 之间的相互转换都列出来,都是网上找的资料,我总结一下,先直接上代码,再讲原理。
1.string 转换成 pchar
可以使用 pchar 进行强制类型转换,也可以使用 StrPCopy 函数
- var
- s:string;
- p,p1:PChar;
- begin
- s:='Hello Delphi';
- p:=PChar(s);
- ShowMessage(p);
- p1:=StrAlloc(Length(s)+1);
- StrPCopy(p1,s);
- ShowMessage(p1);
- StrDispose(p1);
- end;
2.pchar 转换成 string
pchar 可以直接当 string 用,也可以用 strpas 函数转换一下
- var
- s,s1,s2:string;
- p:PChar;
- begin
- s:='Hello Delphi';
- p:=PChar(s);
- ShowMessage(p);
- s1:=p;
- ShowMessage(s1);
- s2:=StrPas(p);
- ShowMessage(s2);
- end;
3.char 数组转换成 string
使用 StrPas 函数获取数组的首地址
- var
- c:array [0..11] of Char;
- s:string;
- begin
- c[0]:='H';
- c[1]:='e';
- c[2]:='l';
- c[3]:='l';
- c[4]:='o';
- c[5]:=' ';
- c[6]:='D';
- c[7]:='e';
- c[8]:='l';
- c[9]:='p';
- c[10]:='h';
- c[11]:='i';
- s:=StrPas(@c[0]);
- ShowMessage(s);
- end;
4.string 转 char 数组
使用 move 或者 copymemory 函数
- var
- s:string;
- c:array of Char;
- i:Integer;
- begin
- s:='Hello Delphi';
- SetLength(c,Length(s));
- //Move(s[1],c[0],Length(s));//move和CopyMemory都行
- CopyMemory(@c[0],PChar(s),Length(s));
- for i:=Low(c) to High(c) do
- begin
- ShowMessage(string(c[i]))
- end;
- end;
5.char 数组转 pchar
- var
- c:array [0..11] of Char;
- p:PChar;
- begin
- c:='Hello Delphi';
- //p:=@c[0];
- p:=PChar(@c[0]);
- ShowMessage(StrPas(p));
- end;
6.pchar 转 char 数组
使用 move 或者 CopyMemory 函数
- var
- s:string;
- p:PChar;
- c:array of Char;
- i:Integer;
- begin
- s:='Hello Delphi';
- p:=PChar(s);
- SetLength(c,Length(s));
- //Move(p^,c[0],Length(s));//move和CopyMemory都行
- CopyMemory(@c[0],p,Length(s));;
- for i:=Low(c) to High(c) do
- begin
- ShowMessage(string(c[i]))
- end;
- end;
现在讲讲 char 数组、pchar 和 string
string 和 Char 数组都是一块内存, 其中存放连续的字符. string 保存具体字符的内存对用户是透明的, 由 Delphi 管理它的分配, 复制和释放, 用户不能干预 (其实也可以, 不过是通过非法途径). Char 数组就不必说了吧? 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).
注:因为 string 和 char 数组都是连续的,所以指向 string 的首地址的指针为 @s[1],指向 char 数组的首地址的指针为 @c[0]。pchar 是以 #0 结尾的,所以很多关于 pchar
的函数的使用的时候要注意,如使用 StrAlloc 函数给 pchar 分配内存的时候和使用 StrPCopy 函数的时候
7. 使用 StrAlloc 函数将一个 string 转换给 pchar
- var
- p:PChar;
- s:string;
- begin
- s:='ABCDEF';
- p:=StrAlloc(Length(s));
- Move(s[1],p^,Length(s));
- ShowMessage(StrPas(p));
- StrDispose(p);
- end;
执行以上代码的时候,字符串后面有乱码,查看 delphi 帮助里面关于 StrAlloc 函数
delphi 的帮助如下:
StrAlloc allocates a buffer for a null-terminated string with a maximum length ofSize - 1 (1 byte must be reserved for the termination character).
StrAlloc 函数给 pchar 指向的字符串分配的实力内存为 size-1 个字节,所以我们要多分配一个字节的内存,用来存 pchar 的结束标志 #0
正确使用如下:
- var
- p:PChar;
- s:string;
- begin
- s:='ABCDEF';
- p:=StrAlloc(Length(s)+1);
- Move(s[1],p^,Length(s)+1);//将s的内容按照字节复制到p里面
- //Move(s[1],p^,Length(s)); //执行这句会出现乱码
- ShowMessage(StrPas(p));
- StrDispose(p);
- end;
8. 使用 StrPCopy 将 string 转换成 char 数组
- var
- s:string;
- c:array of Char;
- i:Integer;
- begin
- s:='Hello Delphi';
- SetLength(c,Length(s));
- StrPCopy(@c[0],s);
- for i:=Low(c) to High(c) do
- begin
- ShowMessage(string(c[i]))
- end;
- end;
以上代码执行的时候会报错,查看 delphi 帮助才知道,strpcopy 函数不做长度检查,需要程序员自己控制。
delphi 帮助如下:
StrPCopy copies Source into a null-terminated string Dest. It returns a pointer to Dest.
StrPCopy does not perform any length checking.
The destination buffer must have room for at least Length(Source)+1 characters
正确代码如下:
- var
- s:string;
- c:array of Char;
- i:Integer;
- begin
- s:='Hello Delphi';
- SetLength(c,Length(s)+1);
- StrPCopy(@c[0],s);
- for i:=Low(c) to High(c) do
- begin
- ShowMessage(string(c[i]))
- end;
- end;
使用 strpcopy 函数的时候一定要保证目的 pchar 的长度至少是源字符串的长度 + 1
来源: